Skip to content
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

feat(v2): add support for RTL direction #4140

Merged
merged 14 commits into from
Feb 10, 2021
2 changes: 1 addition & 1 deletion packages/docusaurus-module-type-aliases/src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ declare module '@generated/i18n' {
defaultLocale: string;
locales: [string, ...string[]];
currentLocale: string;
localeConfigs: Record<string, {label: string}>;
localeConfigs: Record<string, {label: string; direction: string}>;
};
export default i18n;
}
Expand Down
6 changes: 4 additions & 2 deletions packages/docusaurus-theme-classic/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,17 @@
"@types/react-toggle": "^4.0.2",
"clsx": "^1.1.1",
"copy-text-to-clipboard": "^2.2.0",
"infima": "0.2.0-alpha.18",
"infima": "0.2.0-alpha.19",
"joi": "^17.2.1",
"lodash": "^4.17.19",
"parse-numeric-range": "^1.2.0",
"postcss": "^7.0.2",
"prism-react-renderer": "^1.1.1",
"prismjs": "^1.23.0",
"prop-types": "^15.7.2",
"react-router-dom": "^5.2.0",
"react-toggle": "^4.1.1"
"react-toggle": "^4.1.1",
"rtlcss": "^2.6.2"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "2.0.0-alpha.70"
Expand Down
43 changes: 42 additions & 1 deletion packages/docusaurus-theme-classic/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import {Plugin} from '@docusaurus/types';
import {getTranslationFiles, translateThemeConfig} from './translations';
import path from 'path';
import Module from 'module';
import postcss from 'postcss';
import rtlcss from 'rtlcss';

const createRequire = Module.createRequire || Module.createRequireFromPath;
const requireFromDocusaurusCore = createRequire(
Expand Down Expand Up @@ -59,15 +61,23 @@ const noFlashColorMode = ({defaultMode, respectPrefersColorScheme}) => {
})();`;
};

function getInfimaCSSFile(direction) {
return `infima/dist/css/default/default${
direction === 'rtl' ? '-rtl' : ''
}.css`;
}

export default function docusaurusThemeClassic(
context,
options,
): Plugin<null, unknown> {
const {
siteConfig: {themeConfig},
i18n: {currentLocale, localeConfigs},
} = context;
const {colorMode, prism: {additionalLanguages = []} = {}} = themeConfig || {};
const {customCss} = options || {};
const {direction} = localeConfigs[currentLocale];

return {
name: 'docusaurus-theme-classic',
Expand Down Expand Up @@ -95,7 +105,7 @@ export default function docusaurusThemeClassic(

getClientModules() {
const modules = [
require.resolve('infima/dist/css/default/default.css'),
require.resolve(getInfimaCSSFile(direction)),
path.resolve(__dirname, './prism-include-languages'),
];

Expand Down Expand Up @@ -135,6 +145,37 @@ export default function docusaurusThemeClassic(
};
},

configurePostCss(postCssOptions) {
if (direction === 'rtl') {
postCssOptions.plugins.push(
postcss.plugin('RtlCssPlugin', () => {
function isInfimaCSSFile(file) {
return (
file.endsWith(getInfimaCSSFile(direction)) ||
// special case for our own monorepo using symlinks!
file.endsWith(
'infima/packages/core/dist/css/default/default-rtl.css',
)
);
}

return function (root: any) {
const file = root?.source.input.file;

// Skip Infima as we are using the its RTL version.
if (isInfimaCSSFile(file)) {
return;
}

rtlcss.process(root);
};
}),
);
}

return postCssOptions;
},

injectHtmlTags() {
return {
preBodyTags: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,10 @@ function DocPageContent({
role="button"
onKeyDown={toggleSidebar}
onClick={toggleSidebar}>
<IconArrow aria-label="Expand sidebar" />
<IconArrow
aria-label="Expand sidebar"
className={styles.expandSidebarButtonIcon}
/>
</div>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@
background-color: var(--ifm-color-emphasis-200);
}

.expandSidebarButtonIcon {
transform: rotate(0);
}
html[dir='rtl'] .expandSidebarButtonIcon {
transform: rotate(180deg);
}

html[data-theme='dark'] .collapsedDocSidebar:hover,
html[data-theme='dark'] .collapsedDocSidebar:focus {
background-color: var(--collapse-button-bg-color-dark);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@
transform: rotate(180deg);
margin-top: 4px;
}
html[dir='rtl'] .collapseSidebarButtonIcon {
transform: rotate(0);
}

html[data-theme='dark'] .collapseSidebarButton {
background-color: var(--collapse-button-bg-color-dark);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ function CanonicalUrlHeaders({permalink}: {permalink?: string}) {
export default function LayoutHead(props: Props): JSX.Element {
const {
siteConfig,
i18n: {currentLocale},
i18n: {currentLocale, localeConfigs},
} = useDocusaurusContext();
const {
favicon,
Expand All @@ -98,11 +98,12 @@ export default function LayoutHead(props: Props): JSX.Element {
// See https://github.com/facebook/docusaurus/issues/3317#issuecomment-754661855
// const htmlLang = currentLocale.split('-')[0];
const htmlLang = currentLocale; // should we allow the user to override htmlLang with localeConfig?
const htmlDir = localeConfigs[currentLocale].direction;

return (
<>
<Head>
<html lang={htmlLang} />
<html lang={htmlLang} dir={htmlDir} />
{metaTitle && <title>{metaTitle}</title>}
{metaTitle && <meta property="og:title" content={metaTitle} />}
{favicon && <link rel="shortcut icon" href={faviconUrl} />}
Expand Down
1 change: 1 addition & 0 deletions packages/docusaurus-types/src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ export type TranslationFiles = TranslationFile[];

export type I18nLocaleConfig = {
label: string;
direction: string;
};

export type I18nConfig = {
Expand Down
2 changes: 1 addition & 1 deletion packages/docusaurus/src/server/__tests__/i18n.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ describe('loadI18n', () => {
locales: ['en', 'fr', 'de'],
currentLocale: 'de',
localeConfigs: {
fr: {label: 'Français'},
fr: {label: 'Français', direction: 'ltr'},
en: defaultLocaleConfig('en'),
de: defaultLocaleConfig('de'),
},
Expand Down
1 change: 1 addition & 0 deletions packages/docusaurus/src/server/configValidation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ const PresetSchema = Joi.alternatives().try(

const LocaleConfigSchema = Joi.object({
label: Joi.string(),
direction: Joi.string().equal('ltr', 'rtl').default('ltr'),
});

const I18N_CONFIG_SCHEMA = Joi.object<I18nConfig>({
Expand Down
1 change: 1 addition & 0 deletions packages/docusaurus/src/server/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {normalizeUrl} from '@docusaurus/utils';
export function defaultLocaleConfig(locale: string): I18nLocaleConfig {
return {
label: locale,
direction: 'ltr',
};
}

Expand Down
25 changes: 15 additions & 10 deletions packages/docusaurus/src/webpack/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import merge from 'webpack-merge';
import webpack, {
Configuration,
Loader,
NewLoader,
Plugin,
RuleSetRule,
Stats,
Expand Down Expand Up @@ -182,21 +181,27 @@ export function applyConfigurePostCss(
): Configuration {
type LocalPostCSSLoader = Loader & {options: {postcssOptions: any}};

// TODO not ideal heuristic but good enough for our usecase?
function isPostCssLoader(loader: Loader): loader is LocalPostCSSLoader {
// TODO not ideal heuristic but good enough for our usecase?
return !!(loader as any)?.options?.postcssOptions;
}

// Does not handle all edge cases, but good enough for now
config.module?.rules.map((rule) => {
for (const loader of rule.use as NewLoader[]) {
if (isPostCssLoader(loader)) {
loader.options.postcssOptions = configurePostCss(
loader.options.postcssOptions,
);
}
function overridePostCssOptions(entry) {
if (isPostCssLoader(entry)) {
entry.options.postcssOptions = configurePostCss(
entry.options.postcssOptions,
);
} else if (Array.isArray(entry.oneOf)) {
entry.oneOf.forEach(overridePostCssOptions);
} else if (Array.isArray(entry.use)) {
entry.use
.filter((u) => typeof u === 'object')
.forEach(overridePostCssOptions);
}
});
}

config.module?.rules.forEach(overridePostCssOptions);

return config;
}
Expand Down
5 changes: 5 additions & 0 deletions website/docs/api/docusaurus.config.js.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,20 @@ module.exports = {
localeConfigs: {
en: {
label: 'English',
direction: 'ltr',
},
fr: {
label: 'Français',
direction: 'ltr',
},
},
},
};
```

- `label`: the label to use for this locale
- `direction`: `ltr` (default) or `rtl` (for [right-to-left languages](https://developer.mozilla.org/en-US/docs/Glossary/rtl) like Araric, Hebrew...)

### `noIndex`

- Type: `boolean`
Expand Down
2 changes: 1 addition & 1 deletion website/docs/i18n/i18n-introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ The goals of the Docusaurus i18n system are:
- **No coupling**: not forced to use any SaaS, yet the integration is possible.
- **Easy to use with [Crowdin](http://crowdin.com/)**: multiple Docusaurus v1 sites use Crowdin, and should be able to migrate to v2.
- **Good SEO defaults**: setting useful SEO headers like [`hreflang`](https://developers.google.com/search/docs/advanced/crawling/localized-versions) for you.
- **RTL support**: locales reading right-to-left (Arabic, Hebrew...) should be easy to use.

### i18n goals (TODO)

Features that are **not yet implemented**:

- **RTL support**: one locale should not be harder to use than another.
- **Contextual translations**: reduce friction to contribute to the translation effort.
- **Anchor links**: linking should not break when you localize headings.
- **Advanced configuration options**: customize route paths, file-system paths.
Expand Down
47 changes: 37 additions & 10 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1212,6 +1212,13 @@
resolved "https://registry.yarnpkg.com/@bugsnag/safe-json-stringify/-/safe-json-stringify-6.0.0.tgz#22abdcd83e008c369902976730c34c150148a758"
integrity sha512-htzFO1Zc57S8kgdRK9mLcPVTW1BY2ijfH7Dk2CeZmspTWKdKqSo1iwmqrq2WtRjFlo8aRZYgLX0wFrDXF/9DLA==

"@choojs/findup@^0.2.1":
version "0.2.1"
resolved "https://registry.yarnpkg.com/@choojs/findup/-/findup-0.2.1.tgz#ac13c59ae7be6e1da64de0779a0a7f03d75615a3"
integrity sha512-YstAqNb0MCN8PjdLCDfRsBcGVRN41f3vgLvaI0IrIcBp4AqILRSS0DeWNGkicC+f/zRIPJLc+9RURVSepwvfBw==
dependencies:
commander "^2.15.1"

"@cnakazawa/watch@^1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.3.tgz#099139eaec7ebf07a27c1786a3ff64f39464d2ef"
Expand Down Expand Up @@ -6244,7 +6251,7 @@ comma-separated-tokens@^1.0.0:
resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.7.tgz#419cd7fb3258b1ed838dc0953167a25e152f5b59"
integrity sha512-Jrx3xsP4pPv4AwJUDWY9wOXGtwPXARej6Xd99h4TUGotmf8APuquKMpK+dnD3UgyxK7OEWaisjZz+3b5jtL6xQ==

commander@^2.19.0, commander@^2.20.0, commander@^2.20.3, commander@^2.3.0, commander@^2.8.1:
commander@^2.15.1, commander@^2.19.0, commander@^2.20.0, commander@^2.20.3, commander@^2.3.0, commander@^2.8.1:
version "2.20.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
Expand Down Expand Up @@ -10777,10 +10784,10 @@ infer-owner@^1.0.3, infer-owner@^1.0.4:
resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467"
integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==

infima@0.2.0-alpha.18:
version "0.2.0-alpha.18"
resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.18.tgz#8ac62711f13ef99b1f4a45b3ac14571722a2ccf6"
integrity sha512-ndSEffXzjgM/eiSm5jpLTX6ON9MmylzxqBnV2bTiC3kCSyDYdvzTs+bSwf+C4TWayuqnRTnBK1JUePo3m6Bnfg==
infima@0.2.0-alpha.19:
version "0.2.0-alpha.19"
resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.19.tgz#037dbb0b03e3aff00fb9b5e39f360b22645da6d6"
integrity sha512-3ZWyljOy6xNbOsEXJ2wecj3yXtL2vno4PbAEekTQxsSt6fu4kIOnleZH8RSW9ZLbWnaAokZgoJsAZZk3dI4hcg==

inflight@^1.0.4:
version "1.0.6"
Expand Down Expand Up @@ -16092,6 +16099,15 @@ postcss-zindex@^4.0.1:
postcss "^7.0.0"
uniqs "^2.0.0"

postcss@^6.0.23:
version "6.0.23"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324"
integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==
dependencies:
chalk "^2.4.1"
source-map "^0.6.1"
supports-color "^5.4.0"

postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.18, postcss@^7.0.2, postcss@^7.0.21, postcss@^7.0.23, postcss@^7.0.26, postcss@^7.0.27, postcss@^7.0.31, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6, postcss@^7.0.7:
version "7.0.32"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d"
Expand Down Expand Up @@ -17680,6 +17696,17 @@ rsvp@^4.8.4:
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734"
integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==

rtlcss@^2.6.2:
version "2.6.2"
resolved "https://registry.yarnpkg.com/rtlcss/-/rtlcss-2.6.2.tgz#55b572b52c70015ba6e03d497e5c5cb8137104b4"
integrity sha512-06LFAr+GAPo+BvaynsXRfoYTJvSaWRyOhURCQ7aeI1MKph9meM222F+Zkt3bDamyHHJuGi3VPtiRkpyswmQbGA==
dependencies:
"@choojs/findup" "^0.2.1"
chalk "^2.4.2"
mkdirp "^0.5.1"
postcss "^6.0.23"
strip-json-comments "^2.0.0"

run-async@^2.2.0, run-async@^2.3.0, run-async@^2.4.0:
version "2.4.1"
resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
Expand Down Expand Up @@ -18843,16 +18870,16 @@ strip-indent@^3.0.0:
dependencies:
min-indent "^1.0.0"

strip-json-comments@^2.0.0, strip-json-comments@~2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=

strip-json-comments@^3.0.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==

strip-json-comments@~2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=

strip-outer@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.1.tgz#b2fd2abf6604b9d1e6013057195df836b8a9d631"
Expand Down