អត្ថបទ
លំនាំរចនាស្ថាបត្យកម្មសម្រាប់ layout និង theme ច្រើន
តើគួររៀបចំ frontend មួយឱ្យគាំទ្រ theme 100+ និង layout ច្រើនប្រភេទ ដោយមិនឱ្យ logic ផ្ទាល់ខ្លួនជ្រៀតចូលទៅក្នុង component ដែលប្រើរួមគ្នា ដោយរបៀបណា? អត្ថបទនេះបកស្រាយការបែងចែកស្រទាប់ core / view / theme leaf, ការកំណត់រចនាសម្ព័ន្ធតាមប្រភេទ, ការធ្វើតេស្តភាពពេញលេញរបស់ក្រុម theme និងការផ្ទុក theme CSS តាមតម្រូវការ ព្រមទាំងការដោះដូររបស់ស្រទាប់នីមួយៗ។
· បានធ្វើបច្ចុប្បន្នភាព · អាន 3 នាទី
ខ្ញុំធ្លាប់ទទួលខុសត្រូវលើការរៀបចំស្ថាបត្យកម្មឡើងវិញសម្រាប់ platform frontend ធំមួយដែលប្រើ Nx / Angular។ វាត្រូវគាំទ្រ theme ជាង 100 និង layout ច្រើនប្រភេទ។ ជារឿយៗ សមាជិកផ្សេងៗអនុវត្តកិច្ចការរងដែលពាក់ព័ន្ធនឹង layout និង theme ច្រើន ដោយតាមរបៀបដែលសមនឹងទម្លាប់អភិវឌ្ឍន៍រៀងៗខ្លួន។ នៅពេលបន្តកើនឡើងយូរ វាក្លាយជាបំណុលបច្ចេកទេស ហើយតម្រូវការដូចគ្នាក៏មាន logic អនុវត្តច្រើនបែបដែលដំណើរការព្រមគ្នា។
អត្ថបទនេះពន្យល់ឱ្យច្បាស់ពីការរចនាស្នូលនៅពេលនោះ៖ របៀបបែងចែកស្រទាប់ របៀបរក្សា theme ជាងមួយរយឱ្យពេញលេញ និងរបៀបឱ្យ browser ទាញយកតែ CSS ដែលត្រូវប្រើ។ កូដ production ដើមមិនអាចផ្សព្វផ្សាយបានទេ ដូច្នេះខ្ញុំបានយកកូដដែលបង្កើតថ្មី និង theme ប្រឌិតបី មកអនុវត្តឡើងវិញនៅក្នុង ករណីសិក្សាផ្នែកវិស្វកម្ម frontend ហើយក៏មាន Demo លើអ៊ីនធឺណិត ដែលអាចសាកល្បងបានផ្ទាល់ផងដែរ។ កូដក្នុងអត្ថបទទាំងអស់មកពីកំណែសាធារណៈនេះ។
និយាយសរុបជាមុន៖ បំបែក «រូបរាង» ចេញពី «មុខងារ» រួចឱ្យ compiler និងការធ្វើតេស្តជួយធានាភាពស៊ីសង្វាក់គ្នារបស់ theme ជាងមួយរយ។
បញ្ហាមិនមែនគ្រាន់តែប្ដូរពណ៌ទេ#
ចំណុចចាប់ផ្ដើមដែលជួបញឹកញាប់បំផុតសម្រាប់ការគាំទ្រtheme ច្រើនគឺ បន្ថែមលក្ខខណ្ឌនៅក្នុងសមាសភាគរួម។ ឧទាហរណ៍ theme A ត្រូវការប៊ូតុងមួយទៀត ចំណែកtheme B ត្រូវបញ្ជូនទៅទំព័រផ្សេងក្នុងអំឡុងពេលយុទ្ធនាការ៖
if (theme === 'a') {
showExtraButton = true;
} else if (theme === 'b' && isCampaign) {
redirectTo = '/campaign';
}
ពេលមាន theme តែបី ការសរសេរបែបនេះលឿនណាស់។ ប៉ុន្តែពេល theme កើនដល់មួយរយ រាល់ component ដែលប្រើរួមគ្នាត្រូវផ្ទុក branch ជាច្រើនដែល «មានសុពលភាពតែសម្រាប់ theme ណាមួយប៉ុណ្ណោះ»។ លទ្ធផលគឺ៖
- តម្រូវការកែប្រែ theme A អាចធ្វើឱ្យ theme B ខូចដោយមិនដឹងខ្លួន ហើយគ្មាននរណាទទួលខុសត្រូវពិនិត្យ theme B។
- ភាពខុសគ្នាបែបដូចគ្នាត្រូវបានសរសេរម្តងក្នុង component នីមួយៗ ហើយរបៀបសរសេរក៏មិនដូចគ្នាដែរ។
- ពេលបន្ថែម theme ថ្មី គ្មាននរណាអាចប្រាកដថា «បានបំពេញគ្រប់កន្លែងដែលត្រូវការហើយឬនៅ»។
ដូច្នេះ អ្វីដែលត្រូវដោះស្រាយមិនមែនគ្រាន់តែប្ដូរពណ៌ទេ ប៉ុន្តែគឺ៖ អនុញ្ញាតឱ្យ theme នីមួយៗមានភាពខុសគ្នាផ្នែករូបរាង និងផលិតផល ព្រមទាំងរក្សាក្រុម theme ទាំងមូលឱ្យពេញលេញ និងអាចទុកចិត្តបាន។
បែងចែកឱ្យច្បាស់ជាមុន៖ layout និង theme ជារឿងពីរផ្សេងគ្នា#
ការប្រៀបធៀបនឹងផ្ទះជួយឱ្យយល់ងាយបំផុត៖
- រចនាសម្ព័ន្ធ និងបណ្ដាញបំពង់៖ សសរ ប្រព័ន្ធទឹក និងភ្លើង។ គ្រប់ផ្ទះដូចគ្នា ហើយក៏មិនគួរកែប្រែតាមចំណង់ចំណូលចិត្តរបស់អ្នករស់នៅដែរ។
- layout៖ ការរៀបបន្ទប់។ មានបន្ទប់គេងពីរ ឬបី បន្ទប់ទទួលភ្ញៀវនៅឯណា។ វាកំណត់ថា «របស់របររៀបចំយ៉ាងដូចម្ដេច»។
- theme៖ ការតុបតែង។ ពណ៌ជញ្ជាំង សម្ភារៈ និងទំហំជ្រុងមូល។ វាកំណត់ថា «របស់របរមានរូបរាងយ៉ាងដូចម្ដេច»។
នៅក្នុង frontend ចំណុចទាំងបីនេះត្រូវនឹងស្រទាប់ផ្សេងៗគ្នា។ បើលាយបញ្ចូលគ្នា នឹងកើតមានស្ថានការណ៍ដូចជា «កែ data flow ដើម្បីប្ដូរពណ៌»។
រចនាសម្ព័ន្ធបួនស្រទាប់#
Runtime theme id
│
▼
selector ──► theme leaf (complete typed config)
│
▼
shared view ◄── data service
│ └──► actions facade
▼
pure core
មើលពីក្រោមឡើងលើ៖
core៖ គ្រប់គ្រងតែការបង្ហាញ#
component core ទទួលតែទិន្នន័យដែល «បានរៀបចំរួចរាល់ ហើយអាច render បានភ្លាមៗ» និងបញ្ចេញតែចេតនារបស់អ្នកប្រើប្រាស់ (intent) ប៉ុណ្ណោះ។ វាមិនដឹងថាបច្ចុប្បន្នជាអ្នកប្រើ theme ណាទេ មិនពាក់ព័ន្ធនឹង routing ឬទម្រង់ទិន្នន័យដែល API ត្រឡប់មកវិញ ហើយក៏មិនយោងទៅកាន់សម្ភារៈម៉ាកណាមួយដែរ។
export class ThemeCardCoreComponent {
readonly appearance = input.required<ThemeAppearance>();
readonly content = input.required<ThemeContent>();
readonly items = input.required<readonly ShowcaseItem[]>();
readonly selectedId = input<string | null>(null);
readonly itemSelected = output<ShowcaseItem>();
readonly selectionCleared = output<void>();
}
core ត្រូវបានប្រើរួមគ្នាដោយ theme ទាំងអស់ ដូច្នេះវិសាលភាពផលប៉ះពាល់របស់វាធំជាងគេ ហើយច្បាប់របស់វាក៏តឹងរ៉ឹងបំផុតដែរ៖ ទទួលចូលតែអ្វីដែលចាំបាច់ និងបញ្ចេញតែ intent ប៉ុណ្ណោះ។
view៖ ទទួលខុសត្រូវលើការសម្របសម្រួល#
view ជាអ្នកសម្របសម្រួលនៅចន្លោះ។ វាទទួលទិន្នន័យពី data service រួចបម្លែងទៅជាទម្រង់ដែល core ត្រូវការ។ ពេល core បញ្ចេញ intent វាបញ្ជូនទៅឱ្យ actions facade ដោះស្រាយ។
@Component({
selector: 'case-study-theme-card-view',
providers: [FeatureActionsFacade, FeatureDataService],
template: `
<case-study-theme-card-core
[appearance]="appearance()"
[content]="themeContent()"
[items]="data.items()"
[selectedId]="actions.selectedId()"
(itemSelected)="select($event)"
(selectionCleared)="actions.reset()"
/>
`,
})
export class ThemeCardViewComponent { /* ... */ }
ប្រភពទិន្នន័យ (data service) និងសកម្មភាពពេលចុច (actions facade) សុទ្ធតែមានព្រំដែនច្បាស់លាស់រៀងៗខ្លួន មិនរាយប៉ាយក្នុង component បង្ហាញទេ។
layout សមស្របនឹងការដាក់នៅស្រទាប់នេះ។ layout ផ្សេងៗអាចជាផ្នែក shared view ផ្សេងៗគ្នា ដែលប្រើ data service និង facade ដូចគ្នា តែផ្សំ core ជាលំដាប់រៀបចំខុសគ្នា។ ដើម្បីឱ្យសាមញ្ញ Demo សាធារណៈមាន shared view តែមួយប៉ុណ្ណោះ។ ចំណែកការរៀបចំ production ឡើងវិញនៅពេលនោះ បានបញ្ចូល shared view ចំនួន 26។
theme leaf៖ theme នីមួយៗមាន node ស្លឹកមួយ#
theme នីមួយៗជាកម្មវិធី component ស្ដើងមួយ ដែលធ្វើតែរឿងមួយប៉ុណ្ណោះ៖ ជ្រើសរើសការកំណត់រូបរាងមួយដែលពេញលេញ ហើយបញ្ជូនទៅ shared view។
@Component({
selector: 'case-study-theme-aurora',
imports: [ThemeCardViewComponent],
template:
'<case-study-theme-card-view [appearance]="appearance" data-theme-leaf="aurora" />',
})
export class ThemeAuroraComponent {
protected readonly appearance = THEME_APPEARANCES.aurora;
}
នៅខាងក្នុងគ្មានលក្ខខណ្ឌអាជីវកម្មណាមួយទេ។ នៅក្នុង production ក្រោយពេល refactor រួច theme leaf ពេញលេញមួយដែលតំណាងឱ្យលំនាំនេះមាន 23 បន្ទាត់។ រីឯវិធីសរសេរចាស់ៗ ផ្លូវតែមួយដូចគ្នានេះមានរាប់រយបន្ទាត់។
selector៖ រាយបញ្ជីសមាជិកគ្រួសារឱ្យច្បាស់#
selector ប្រើ theme id របស់ runtime ដើម្បី render leaf ដែលត្រូវគ្នា៖
@switch (theme()) {
@case ('aurora') { <case-study-theme-aurora /> }
@case ('summit') { <case-study-theme-summit /> }
@default { <case-study-theme-default /> }
}
វាមើលទៅសាមញ្ញធម្មតា ប៉ុន្តែចំណុចសំខាន់គឺ «ច្បាស់លាស់»៖ អាចមើលឃើញភ្លាមៗថាមាន theme អ្វីខ្លះ និង theme នីមួយៗត្រូវនឹង leaf មួយណា ហើយការធ្វើតេស្តក៏អាចពិនិត្យម្តងមួយៗបានដែរ។
ឱ្យ compiler ជួយរាយឈ្មោះពិនិត្យ#
ពេល theme កាន់តែច្រើន អ្វីដែលគួរឱ្យបារម្ភបំផុតគឺការខកខាន។ បន្ថែម theme ថ្មីហើយភ្លេចបន្ថែមការកំណត់ ឬប្ដូរទម្រង់ការកំណត់ហើយ theme ចាស់មួយចំនួនមិនបានកែតាម។
វិធីធ្វើគឺសរសេរបញ្ជី theme ជាប្រភពតែមួយជាមុន រួចប្រើ satisfies របស់ TypeScript ដើម្បីតម្រូវឱ្យ theme នីមួយៗមានការកំណត់ពេញលេញមួយ៖
export const DEMO_THEMES = ['default', 'aurora', 'summit'] as const;
export type DemoTheme = (typeof DEMO_THEMES)[number];
export interface ThemeAppearance {
readonly density: 'comfortable' | 'compact';
readonly id: DemoTheme;
readonly stylesheetHref: `themes/${string}.css`;
}
export const THEME_APPEARANCES = {
default: { id: 'default', density: 'comfortable', stylesheetHref: 'themes/default.css' },
aurora: { id: 'aurora', density: 'comfortable', stylesheetHref: 'themes/aurora.css' },
summit: { id: 'summit', density: 'compact', stylesheetHref: 'themes/summit.css' },
} satisfies Record<DemoTheme, ThemeAppearance>;
បន្ថែម theme មួយទៀតក្នុង DEMO_THEMES តែខកខានមិនបំពេញ THEME_APPEARANCES នោះ ការចងក្រងនឹងបរាជ័យ។ សរសេរឈ្មោះ field ខុស ឬទម្រង់ផ្លូវ CSS មិនត្រឹមត្រូវ ក៏ដូចគ្នាដែរ។
អត្ថប្រយោជន៍របស់ satisfies បើប្រៀបនឹងការកំណត់ type ដោយផ្ទាល់ គឺវាពិនិត្យទម្រង់ ប៉ុន្តែរក្សាប្រភេទជាក់លាក់របស់តម្លៃនីមួយៗ។ ដូច្នេះ ពេលយក THEME_APPEARANCES.aurora ទៅប្រើពេលក្រោយ ប្រភេទវាមិនត្រូវបន្ធូរទៅជាប្រភេទទូទៅដូចជា ThemeAppearance ទេ។
ឱ្យការធ្វើតេស្តការពារក្រុម theme ទាំងមូល#
compiler អាចពិនិត្យការកំណត់បាន ប៉ុន្តែមិនអាចពិនិត្យថា «theme នេះពិតជាអាច render បានឬអត់» ទេ។ ចំណុចនេះទុកឱ្យការធ្វើតេស្តភាពពេញលេញរបស់ក្រុម theme ដោះស្រាយ ដោយរាយ theme ដែលបានប្រកាសទាំងអស់ម្តងមួយៗ៖
it.each(DEMO_THEMES)('renders the %s family leaf', (theme) => {
const fixture = TestBed.createComponent(ThemeSelectorComponent);
fixture.componentRef.setInput('theme', theme);
fixture.detectChanges();
expect(
fixture.nativeElement.querySelector(`[data-theme-leaf="${theme}"]`),
).toBeTruthy();
});
ផ្នែកការកំណត់ក៏មានការធ្វើតេស្តដែលត្រូវគ្នាដែរ៖ field id ក្នុងការកំណត់ theme នីមួយៗ ត្រូវតែដូចនឹង key របស់វាក្នុងតារាងការកំណត់ ហើយផ្លូវ CSS ក៏ត្រូវតែគោរពតាមច្បាប់របស់ក្រុម theme ផងដែរ។
ការត្រួតពិនិត្យទាំងពីរប្រភេទនេះរួមគ្នា បម្លែងការងារដែលពីមុនត្រូវពឹងលើមនុស្សពិនិត្យដោយដៃថា «មាន theme បងប្អូនណាខកខានឬអត់» ទៅជាកំហុសដែល CI នឹងរារាំង។ សម្រាប់ theme ជាងមួយរយ មនុស្សមិនអាចមើលពិនិត្យអស់ទេ។
ទាញយកតែ theme CSS ដែលកំពុងប្រើ#
ការបែងចែកស្រទាប់ដោះស្រាយបញ្ហាថែទាំ ប៉ុន្តែ theme ច្រើននៅមានចំណាយមួយទៀតដែលប៉ះពាល់អ្នកប្រើប្រាស់ដោយផ្ទាល់ គឺ CSS។
ពីមុន គេដាក់ stylesheet theme ចំនួន 136 ទាំងអស់ជាមួយគ្នាក្នុង bundle មួយ។ អ្នកប្រើមិនថាប្រើ theme មួយណាទេ ក៏ត្រូវទាញយក និង parse ទាំងអស់ដែរ។ ក្រោយប្ដូរមកផ្ទុកតាមតម្រូវការ ទំហំធនធានរបស់ theme មួយបានធ្លាក់ចុះពីប្រហែល 2.4 MB មកត្រឹម 17 KB គឺថយចុះប្រហែល 99%។
យន្តការនេះសាមញ្ញណាស់៖ ការកំណត់ theme នីមួយៗប្រកាស stylesheetHref របស់ខ្លួន ហើយ មានតែ loader មួយប៉ុណ្ណោះដែលគ្រប់គ្រង theme <link> មួយនៅលើទំព័រ៖
@Injectable()
export class ThemeStylesheetLoader {
readonly #document = inject(DOCUMENT);
load(href: ThemeAppearance['stylesheetHref']): void {
const id = 'case-study-theme-stylesheet';
const existing = this.#document.getElementById(id) as HTMLLinkElement | null;
const link = existing ?? this.#document.createElement('link');
link.id = id;
link.rel = 'stylesheet';
if (link.getAttribute('href') !== href) link.setAttribute('href', href);
if (!existing) this.#document.head.append(link);
}
}
ពេលប្ដូរ theme platform ហៅវា៖
effect(() => {
const appearance = THEME_APPEARANCES[this.selectedTheme()];
this.#stylesheetLoader.load(appearance.stylesheetHref);
});
ចំណុចសំខាន់គឺ «តែមួយ»។ បើកន្លែងនីមួយៗបន្ថែម <link> ដោយខ្លួនឯង ក្រោយប្ដូរទៅមកជាច្រើនដង style របស់ theme ចាស់អាចនៅសល់ ឬ CSS ពីរឈុតអាចជាន់គ្នាទៅវិញទៅមក។ ការធ្វើតេស្តនឹងបញ្ជាក់ថា ទោះបីប្ដូរច្រើនដងក៏ដោយ នៅលើទំព័រនៅតែមាន stylesheet ដែលគ្រប់គ្រងដោយប្រព័ន្ធតែមួយប៉ុណ្ណោះ។
theme CSS ខ្លួនវាកំណត់តែ design token (អថេរ CSS) ប៉ុណ្ណោះ ហើយ style របស់ core គ្រាន់តែអានអថេរទាំងនោះ៖
:root {
--demo-surface: #fffaf1;
--demo-text: #3b2620;
--demo-accent: #c65367;
--demo-radius: 30px;
}
ដូច្នេះ ការប្ដូរ theme គ្រាន់តែប្ដូរតារាងអថេរមួយប៉ុណ្ណោះ ហើយ style របស់ core មិនចាំបាច់កែប្រែទាល់តែសោះ។ របៀបភ្លឺ និងងងឹតគឺជាក្រុមអថេរមួយទៀតក្នុងឯកសារតែមួយ។
ការដោះដូរ#
ការរចនានេះក៏មានចំណាយដែរ៖
- ឯកសារកើនច្រើន។ theme នីមួយៗមាន leaf មួយ ហើយ layout នីមួយៗមាន view មួយ ដូច្នេះចំនួនឯកសារតូចៗកើនឡើង។ អ្វីដែលទទួលបានមកវិញគឺ អាចមើលឃើញច្បាស់ភ្លាមៗពីទំនួលខុសត្រូវរបស់ឯកសារនីមួយៗ ហើយអាចពិនិត្យភាពពេញលេញបាន។
- ការកំណត់មិនគួរក្លាយជាភាសាសរសេរកម្មវិធីទេ។ config សមស្របសម្រាប់ពិពណ៌នារូបរាង និងភាពខុសគ្នាដែលមានព្រំដែនច្បាស់។ បើចាប់ផ្ដើមសរសេរលក្ខខណ្ឌ និងលំហូរក្នុងការកំណត់ នោះគ្រាន់តែយក if/else ដើមទៅលាក់នៅកន្លែងផ្សេងប៉ុណ្ណោះ។
- core ត្រូវការការធ្វើតេស្តកិច្ចសន្យាដែលរឹងមាំជាងមុន។ វាត្រូវបានប្រើរួមគ្នាដោយ theme ទាំងអស់ ដូច្នេះការកែប្រែមួយអាចប៉ះពាល់ដល់ theme ជាងមួយរយ។
- ការប្ដូរ CSS នៅ runtime ត្រូវការអ្នកទទួលខុសត្រូវតែម្នាក់។ ការស្នើសុំ stylesheet ដោយគ្មានការសម្របសម្រួលអាចបង្កការភ្លឹបភ្លែត ឬទុក style ចាស់ឱ្យនៅសល់។ នេះហើយជាមូលហេតុដែល loader ត្រូវមានតែមួយ។
- cache នៅតែសំខាន់។ ទោះបីផ្ទុក theme តែមួយក៏ដោយ ឈ្មោះឯកសារដែលមានស្ថិរភាព និង cache header នៅតែកំណត់ល្បឿនពេលអ្នកប្រើត្រឡប់មកម្តងទៀត។
ពេលណាគួរប្រើវិធីនេះ#
បើផលិតផលរបស់អ្នកមានតែរបៀបភ្លឺ និងងងឹតពីរប៉ុណ្ណោះ CSS variables គ្រប់គ្រាន់ហើយ មិនចាំបាច់ប្រើរចនាសម្ព័ន្ធទាំងមូលនេះទេ។
ពេលអ្នកចាប់ផ្ដើមជួបស្ថានការណ៍ទាំងនេះ គួរពិចារណាវិធីនេះ៖
- theme ឬកំណែសម្រាប់អតិថិជនមានលើសដប់ ហើយនៅតែកើនឡើង។
- ភាពខុសគ្នារវាង theme មិនមែនត្រឹមតែពណ៌ទេ តែមានទាំង layout, feature flag និងអត្ថបទផងដែរ។
- តម្រូវការកែ theme មួយជារឿយៗប៉ះពាល់ដល់ theme មួយទៀតដោយអចេតនា។
- ពេលបន្ថែម theme ថ្មី គ្មាននរណាអាចប្រាកដថាត្រូវបំពេញកន្លែងណាខ្លះទេ។
ព្រំដែននៃភស្តុតាង#
ត្រូវបញ្ជាក់ឱ្យច្បាស់ពីវិសាលភាពនៃតួលេខ production ដែលបានលើកឡើងក្នុងអត្ថបទនេះ៖
- 23 បន្ទាត់ គឺជា theme leaf ពេញលេញមួយដែលតំណាងឱ្យលំនាំនេះ ក្រោយ refactor រួច។ មិនមែនមានន័យថា leaf ឬឯកសារទាំងអស់មាន 23 បន្ទាត់ទេ។
- migration នៅពេលនោះបានបញ្ចូល module ចំនួន 70 ក្នុងស្ថាបត្យកម្មថ្មី (facade ចំនួន 24, data service ចំនួន 10, theme config ចំនួន 10 និង shared view ចំនួន 26)។ នេះជាវិសាលភាពនៃការកែប្រែ មិនមែនជាលទ្ធផលនៃការបង្កើនល្បឿន ឬកាត់បន្ថយកូដទេ។
- 2.4 MB → 17 KB គឺជាលទ្ធផលវាស់វែងជាក់ស្ដែងនៅក្នុង production។ CSS តូចៗទាំងបីក្នុង Demo សាធារណៈមិនអាចបង្ហាញឡើងវិញនូវតួលេខនេះបានទេ។
- ក្នុងគម្រោងគុណភាពតែមួយ Performance របស់ Lighthouse នៅលើទំព័រវាស់វែងសំខាន់ៗបានកើនពី 50+ ដល់ 90+ ប៉ុន្តែវាជាលទ្ធផលរួមពីការកែលម្អជាច្រើន មិនមែនដោយសារផ្ទុក CSS តាមតម្រូវការតែមួយមុខទេ។
repo សាធារណៈបង្ហាញភស្តុតាងអំពីយន្តការស្ថាបត្យកម្មផ្ទាល់៖ កិច្ចសន្យាតាមប្រភេទ ការប្ដូរ runtime ការធ្វើតេស្តភាពពេញលេញរបស់ក្រុម theme, CSS តាមតម្រូវការ និង CI ដែលដំណើរការការត្រួតពិនិត្យទាំងនេះ។ តារាងផ្គូផ្គងការអះអាងពេញលេញមាននៅក្នុង ការធ្វើសវនកម្មព្រំដែនភស្តុតាង របស់ repo។
បើចង់មើលលទ្ធផលផ្ទាល់ អ្នកអាចបើក Demo លើអ៊ីនធឺណិត ដើម្បីប្ដូរ theme បី ភាសា និងរបៀបភ្លឺ/ងងឹត រួចប្រៀបធៀបជាមួយ កូដប្រភពនៅលើ GitHub។