Skip to content

Commit a99e72b

Browse files
feat: add support for right-to-left languages (#101)
Fixes #100
1 parent a7bb396 commit a99e72b

File tree

9 files changed

+102
-32
lines changed

9 files changed

+102
-32
lines changed

examples/sample-docs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@
1010
"ci:build": "run-s clean build"
1111
},
1212
"devDependencies": {
13-
"@climateinteractive/docs-builder": "^1.0.0"
13+
"@climateinteractive/docs-builder": "workspace:*"
1414
}
1515
}

examples/sample-docs/projects/_shared/src/base.css

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -634,10 +634,18 @@ footer {
634634

635635
.responsive-sidebar-visible .content-container {
636636
position: fixed;
637-
left: 300px;
638637
width: 100%;
639638
}
640639

640+
/* rtl:begin:ignore */
641+
.responsive-sidebar-visible[dir='ltr'] .content-container {
642+
left: 300px;
643+
}
644+
.responsive-sidebar-visible[dir='rtl'] .content-container {
645+
right: 300px;
646+
}
647+
/* rtl:end:ignore */
648+
641649
.content-inner-container {
642650
margin-top: 0;
643651
padding: 0 20px;

examples/sample-docs/projects/_shared/src/template-complete.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
</style>
2424
</head>
2525

26-
<body>
26+
<body dir="${LANG_DIR}">
2727

2828
<div class="content-container complete">
2929
<div class="content" id="content">

examples/sample-docs/projects/_shared/src/template-default.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
</script>
3838
</head>
3939

40-
<body>
40+
<body dir="${LANG_DIR}">
4141

4242
<div class="sidebar ${BASE_NAME}">
4343
<div class="sidebar-scroll-container">

examples/sample-docs/projects/_shared/src/template-simple.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<link rel="stylesheet" href="${ASSET-project.css}">
2020
</head>
2121

22-
<body>
22+
<body dir="${LANG_DIR}">
2323

2424
<div class="content-container">
2525
<div class="content-inner-container">

packages/docs-builder/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
"lunr-languages": "^1.9.0",
4545
"mark.js": "^8.11.1",
4646
"marked": "^4.0.10",
47+
"postcss": "^8.5.6",
48+
"postcss-rtlcss": "^5.7.1",
4749
"ps-tree": "^1.2.0",
4850
"puppeteer": "^18.2.1",
4951
"rev-hash": "^3.0.0",

packages/docs-builder/src/build.ts

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import { fileURLToPath } from 'node:url'
55

66
import { findUp, pathExists } from 'find-up'
77
import glob from 'glob'
8+
import postcss from 'postcss'
9+
import postcssRtlCss from 'postcss-rtlcss'
810
import semverCompare from 'semver-compare'
911

1012
import { Assets } from './assets'
@@ -67,8 +69,19 @@ export async function buildDocs(options: BuildOptions): Promise<void> {
6769
* @param enContext The base (English) context.
6870
*/
6971
async function buildLangs(enContext: Context): Promise<void> {
70-
// Process all pages for each supported language
72+
// Process the CSS files to automatically generate RTL styles
7173
const config = enContext.config
74+
const cssFiles: Map<string, string> = new Map()
75+
function processCss(sourceDir: string, fileName: string): void {
76+
const cssPath = resolvePath(sourceDir, fileName)
77+
const srcCssContent = readTextFile(cssPath)
78+
const outCssContent = postcss([postcssRtlCss()]).process(srcCssContent).css
79+
cssFiles.set(fileName, outCssContent)
80+
}
81+
processCss(config.sourceDir, 'base.css')
82+
processCss(config.baseProjDir, 'project.css')
83+
84+
// Process all pages for each supported language
7285
const localizationDir = resolvePath(config.baseProjDir, 'localization')
7386
const langConfigs: LangConfig[] = []
7487
langConfigs.push({ code: 'en', version: config.version })
@@ -88,7 +101,7 @@ async function buildLangs(enContext: Context): Promise<void> {
88101

89102
// Build the docs for this language
90103
try {
91-
await buildLang(context, langConfig)
104+
await buildLang(context, langConfig, cssFiles)
92105

93106
// Generate `en/docs.po`, which contains the base English strings.
94107
// We only need to generate this if this project is translated (has
@@ -109,8 +122,13 @@ async function buildLangs(enContext: Context): Promise<void> {
109122
*
110123
* @param context The language-specific context.
111124
* @param langConfig The version configuration for the language.
125+
* @param cssFiles The map of CSS files to be copied to the output directory.
112126
*/
113-
async function buildLang(context: Context, langConfig: LangConfig): Promise<void> {
127+
async function buildLang(
128+
context: Context,
129+
langConfig: LangConfig,
130+
cssFiles: Map<string, string>
131+
): Promise<void> {
114132
// Check the version of the translation for this language
115133
const baseVersion = context.config.version
116134
let useSavedVersion: boolean
@@ -166,16 +184,21 @@ async function buildLang(context: Context, langConfig: LangConfig): Promise<void
166184
copyToBase(await moduleDir('lunr-languages'), 'lunr.stemmer.support.js')
167185
copyToBase(await moduleDir('mark.js', 'dist'), 'mark.min.js')
168186

169-
// Copy project-specific CSS
170-
copyToBase(context.config.baseProjDir, 'project.css')
187+
// Write the preprocessed CSS files
188+
function writeCssFile(fileName: string): void {
189+
const cssContent = cssFiles.get(fileName)
190+
assets.writeWithHash(cssContent, fileName, context.outDir)
191+
}
192+
writeCssFile('base.css')
193+
writeCssFile('project.css')
171194

172195
// Copy all other assets from the "shared src" directory. Note that glob paths
173196
// have forward slashes only, so convert backslashes here.
174197
const sharedSrcPath = context.config.sourceDir.replaceAll('\\', '/')
175198
const sharedSrcFiles = glob.sync(`${sharedSrcPath}/*`, { nodir: true })
176199
for (const f of sharedSrcFiles) {
177200
const relPath = f.replace(`${sharedSrcPath}/`, '')
178-
if (!relPath.endsWith('.html')) {
201+
if (!relPath.endsWith('.html') && !relPath.endsWith('base.css')) {
179202
copyToBase(context.config.sourceDir, relPath)
180203
}
181204
}

packages/docs-builder/src/gen-html.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,15 @@ export function writeHtmlFile(
357357
switch (id) {
358358
case 'LANG':
359359
return context.lang
360+
case 'LANG_DIR':
361+
switch (context.lang) {
362+
case 'ar':
363+
case 'fa':
364+
case 'he':
365+
return 'rtl'
366+
default:
367+
return 'ltr'
368+
}
360369
case 'BASE_NAME':
361370
return baseName
362371
case 'TOP_LEVEL_TITLE':

pnpm-lock.yaml

Lines changed: 49 additions & 21 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)