Merge pull request #13573 from surajshetty3416/auto-generate-rtl-style

This commit is contained in:
Suraj Shetty 2021-07-23 11:55:43 +05:30 committed by GitHub
commit 50fed0b1ed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 200 additions and 1974 deletions

View file

@ -8,6 +8,7 @@ let yargs = require("yargs");
let cliui = require("cliui")();
let chalk = require("chalk");
let html_plugin = require("./frappe-html");
let rtlcss = require('rtlcss');
let postCssPlugin = require("esbuild-plugin-postcss2").default;
let ignore_assets = require("./ignore-assets");
let sass_options = require("./sass_options");
@ -96,9 +97,9 @@ async function execute() {
await clean_dist_folders(APPS);
}
let result;
let results;
try {
result = await build_assets_for_apps(APPS, FILES_TO_BUILD);
results = await build_assets_for_apps(APPS, FILES_TO_BUILD);
} catch (e) {
log_error("There were some problems during build");
log();
@ -107,13 +108,15 @@ async function execute() {
}
if (!WATCH_MODE) {
log_built_assets(result.metafile);
log_built_assets(results);
console.timeEnd(TOTAL_BUILD_TIME);
log();
} else {
log("Watching for changes...");
}
return await write_assets_json(result.metafile);
for (const result of results) {
await write_assets_json(result.metafile);
}
}
function build_assets_for_apps(apps, files) {
@ -125,6 +128,8 @@ function build_assets_for_apps(apps, files) {
let output_path = assets_path;
let file_map = {};
let style_file_map = {};
let rtl_style_file_map = {};
for (let file of files) {
let relative_app_path = path.relative(apps_path, file);
let app = relative_app_path.split(path.sep)[0];
@ -140,19 +145,32 @@ function build_assets_for_apps(apps, files) {
}
output_name = path.join(app, "dist", output_name);
if (Object.keys(file_map).includes(output_name)) {
if (Object.keys(file_map).includes(output_name) || Object.keys(style_file_map).includes(output_name)) {
log_warn(
`Duplicate output file ${output_name} generated from ${file}`
);
}
file_map[output_name] = file;
if ([".css", ".scss", ".less", ".sass", ".styl"].includes(extension)) {
style_file_map[output_name] = file;
rtl_style_file_map[output_name.replace('/css/', '/css-rtl/')] = file;
} else {
file_map[output_name] = file;
}
}
return build_files({
let build = build_files({
files: file_map,
outdir: output_path
});
let style_build = build_style_files({
files: style_file_map,
outdir: output_path
});
let rtl_style_build = build_style_files({
files: rtl_style_file_map,
outdir: output_path,
rtl_style: true
});
return Promise.all([build, style_build, rtl_style_build]);
});
}
@ -203,7 +221,33 @@ function get_files_to_build(files) {
}
function build_files({ files, outdir }) {
return esbuild.build({
let build_plugins = [
html_plugin,
vue(),
];
return esbuild.build(get_build_options(files, outdir, build_plugins));
}
function build_style_files({ files, outdir, rtl_style=false }) {
let plugins = [];
if (rtl_style) {
plugins.push(rtlcss);
}
let build_plugins = [
ignore_assets,
postCssPlugin({
plugins: plugins,
sassOptions: sass_options
})
];
plugins.push(require("autoprefixer"));
return esbuild.build(get_build_options(files, outdir, build_plugins));
}
function get_build_options(files, outdir, plugins) {
return {
entryPoints: files,
entryNames: "[dir]/[name].[hash]",
outdir,
@ -217,17 +261,9 @@ function build_files({ files, outdir }) {
PRODUCTION ? "production" : "development"
)
},
plugins: [
html_plugin,
ignore_assets,
vue(),
postCssPlugin({
plugins: [require("autoprefixer")],
sassOptions: sass_options
})
],
plugins: plugins,
watch: get_watch_config()
});
};
}
function get_watch_config() {
@ -260,7 +296,8 @@ async function clean_dist_folders(apps) {
let public_path = get_public_path(app);
let paths = [
path.resolve(public_path, "dist", "js"),
path.resolve(public_path, "dist", "css")
path.resolve(public_path, "dist", "css"),
path.resolve(public_path, "dist", "css-rtl")
];
for (let target of paths) {
if (fs.existsSync(target)) {
@ -272,7 +309,11 @@ async function clean_dist_folders(apps) {
}
}
function log_built_assets(metafile) {
function log_built_assets(results) {
let outputs = {};
for (const result of results) {
outputs = Object.assign(outputs, result.metafile.outputs);
}
let column_widths = [60, 20];
cliui.div(
{
@ -287,9 +328,9 @@ function log_built_assets(metafile) {
cliui.div("");
let output_by_dist_path = {};
for (let outfile in metafile.outputs) {
for (let outfile in outputs) {
if (outfile.endsWith(".map")) continue;
let data = metafile.outputs[outfile];
let data = outputs[outfile];
outfile = path.resolve(outfile);
outfile = path.relative(assets_path, outfile);
let filename = path.basename(outfile);
@ -344,7 +385,11 @@ async function write_assets_json(metafile) {
let info = metafile.outputs[output];
let asset_path = "/" + path.relative(sites_path, output);
if (info.entryPoint) {
out[path.basename(info.entryPoint)] = asset_path;
let key = path.basename(info.entryPoint);
if (key.endsWith('.css') && asset_path.includes('/css-rtl/')) {
key = `rtl_${key}`;
}
out[key] = asset_path;
}
}
@ -483,4 +528,4 @@ function log_rebuilt_assets(prev_assets, new_assets) {
log(" " + filename);
}
log();
}
}

View file

@ -403,19 +403,14 @@ frappe.ui.form.PrintView = class {
setup_print_format_dom(out, $print_format) {
this.print_wrapper.find('.print-format-skeleton').remove();
let base_url = frappe.urllib.get_base_url();
let print_css = frappe.assets.bundled_asset('print.bundle.css');
let print_css = frappe.assets.bundled_asset('print.bundle.css', frappe.utils.is_rtl(this.lang_code));
this.$print_format_body.find('html').attr('dir', frappe.utils.is_rtl(this.lang_code) ? 'rtl': 'ltr');
this.$print_format_body.find('html').attr('lang', this.lang_code);
this.$print_format_body.find('head').html(
`<style type="text/css">${out.style}</style>
<link href="${base_url}${print_css}" rel="stylesheet">`
);
if (frappe.utils.is_rtl(this.lang_code)) {
let rtl_css = frappe.assets.bundled_asset('frappe-rtl.bundle.css');
this.$print_format_body.find('head').append(
`<link type="text/css" rel="stylesheet" href="${base_url}${rtl_css}"></link>`
);
}
this.$print_format_body.find('body').html(
`<div class="print-format print-format-preview">${out.html}</div>`
);

View file

@ -1,299 +0,0 @@
{
"css/frappe-web-b4.css": "public/scss/website.scss",
"css/frappe-chat-web.css": [
"public/css/font-awesome.css",
"public/css/octicons/octicons.css",
"public/less/chat.less"
],
"concat:js/moment-bundle.min.js": [
"node_modules/moment/min/moment-with-locales.min.js",
"node_modules/moment-timezone/builds/moment-timezone-with-data.min.js"
],
"js/chat.js": "public/js/frappe/chat.js",
"js/frappe-recorder.min.js": "public/js/frappe/recorder/recorder.js",
"js/checkout.min.js": "public/js/integrations/razorpay.js",
"js/frappe-web.min.js": [
"public/js/frappe/class.js",
"public/js/frappe/polyfill.js",
"public/js/lib/md5.min.js",
"public/js/frappe/provide.js",
"public/js/frappe/format.js",
"public/js/frappe/utils/number_format.js",
"public/js/frappe/utils/utils.js",
"public/js/frappe/utils/common.js",
"public/js/frappe/ui/messages.js",
"public/js/frappe/translate.js",
"public/js/frappe/utils/pretty_date.js",
"public/js/frappe/microtemplate.js",
"public/js/frappe/query_string.js",
"public/js/frappe/upload.js",
"public/js/frappe/model/meta.js",
"public/js/frappe/model/model.js",
"public/js/frappe/model/perm.js",
"website/js/website.js",
"public/js/frappe/socketio_client.js"
],
"js/bootstrap-4-web.min.js": "website/js/bootstrap-4.js",
"js/control.min.js": [
"node_modules/air-datepicker/dist/js/datepicker.min.js",
"node_modules/air-datepicker/dist/js/i18n/datepicker.cs.js",
"node_modules/air-datepicker/dist/js/i18n/datepicker.da.js",
"node_modules/air-datepicker/dist/js/i18n/datepicker.de.js",
"node_modules/air-datepicker/dist/js/i18n/datepicker.en.js",
"node_modules/air-datepicker/dist/js/i18n/datepicker.es.js",
"node_modules/air-datepicker/dist/js/i18n/datepicker.fi.js",
"node_modules/air-datepicker/dist/js/i18n/datepicker.fr.js",
"node_modules/air-datepicker/dist/js/i18n/datepicker.hu.js",
"node_modules/air-datepicker/dist/js/i18n/datepicker.nl.js",
"node_modules/air-datepicker/dist/js/i18n/datepicker.pl.js",
"node_modules/air-datepicker/dist/js/i18n/datepicker.pt-BR.js",
"node_modules/air-datepicker/dist/js/i18n/datepicker.pt.js",
"node_modules/air-datepicker/dist/js/i18n/datepicker.ro.js",
"node_modules/air-datepicker/dist/js/i18n/datepicker.sk.js",
"node_modules/air-datepicker/dist/js/i18n/datepicker.zh.js",
"public/js/frappe/ui/capture.js",
"public/js/frappe/form/controls/control.js"
],
"js/dialog.min.js": [
"public/js/frappe/dom.js",
"public/js/frappe/form/formatters.js",
"public/js/frappe/form/layout.js",
"public/js/frappe/ui/field_group.js",
"public/js/frappe/form/link_selector.js",
"public/js/frappe/form/multi_select_dialog.js",
"public/js/frappe/ui/dialog.js"
],
"css/desk.min.css": [
"public/js/lib/leaflet/leaflet.css",
"public/js/lib/leaflet/leaflet.draw.css",
"public/js/lib/leaflet/L.Control.Locate.css",
"public/js/lib/leaflet/easy-button.css",
"public/css/font-awesome.css",
"public/css/octicons/octicons.css",
"public/less/desk.less",
"public/less/module.less",
"public/less/mobile.less",
"public/less/controls.less",
"public/less/chat.less",
"public/css/fonts/inter/inter.css",
"node_modules/frappe-charts/dist/frappe-charts.min.css",
"node_modules/plyr/dist/plyr.css",
"public/scss/desk.scss"
],
"css/frappe-rtl.css": [
"public/css/bootstrap-rtl.css",
"public/css/desk-rtl.css",
"public/css/report-rtl.css"
],
"css/printview.css": [
"public/css/bootstrap.css",
"public/scss/print.scss"
],
"concat:js/libs.min.js": [
"public/js/lib/Sortable.min.js",
"public/js/lib/jquery/jquery.hotkeys.js",
"node_modules/bootstrap/dist/js/bootstrap.bundle.min.js",
"node_modules/vue/dist/vue.min.js",
"node_modules/moment/min/moment-with-locales.min.js",
"node_modules/moment-timezone/builds/moment-timezone-with-data.min.js",
"node_modules/socket.io-client/dist/socket.io.slim.js",
"node_modules/localforage/dist/localforage.min.js",
"public/js/lib/jSignature.min.js",
"public/js/lib/leaflet/leaflet.js",
"public/js/lib/leaflet/leaflet.draw.js",
"public/js/lib/leaflet/L.Control.Locate.js",
"public/js/lib/leaflet/easy-button.js"
],
"js/desk.min.js": [
"public/js/frappe/translate.js",
"public/js/frappe/class.js",
"public/js/frappe/polyfill.js",
"public/js/frappe/provide.js",
"public/js/frappe/assets.js",
"public/js/frappe/format.js",
"public/js/frappe/form/formatters.js",
"public/js/frappe/dom.js",
"public/js/frappe/ui/messages.js",
"public/js/frappe/ui/keyboard.js",
"public/js/frappe/ui/colors.js",
"public/js/frappe/ui/sidebar.js",
"public/js/frappe/ui/link_preview.js",
"public/js/frappe/request.js",
"public/js/frappe/socketio_client.js",
"public/js/frappe/utils/utils.js",
"public/js/frappe/event_emitter.js",
"public/js/frappe/router.js",
"public/js/frappe/router_history.js",
"public/js/frappe/defaults.js",
"public/js/frappe/roles_editor.js",
"public/js/frappe/module_editor.js",
"public/js/frappe/microtemplate.js",
"public/js/frappe/ui/page.html",
"public/js/frappe/ui/page.js",
"public/js/frappe/ui/slides.js",
"public/js/frappe/ui/onboarding_dialog.js",
"public/js/frappe/ui/find.js",
"public/js/frappe/ui/iconbar.js",
"public/js/frappe/form/layout.js",
"public/js/frappe/ui/field_group.js",
"public/js/frappe/form/link_selector.js",
"public/js/frappe/form/multi_select_dialog.js",
"public/js/frappe/ui/dialog.js",
"public/js/frappe/ui/capture.js",
"public/js/frappe/ui/app_icon.js",
"public/js/frappe/ui/theme_switcher.js",
"public/js/frappe/model/model.js",
"public/js/frappe/db.js",
"public/js/frappe/model/meta.js",
"public/js/frappe/model/sync.js",
"public/js/frappe/model/create_new.js",
"public/js/frappe/model/perm.js",
"public/js/frappe/model/workflow.js",
"public/js/frappe/model/user_settings.js",
"public/js/lib/md5.min.js",
"public/js/frappe/utils/user.js",
"public/js/frappe/utils/common.js",
"public/js/frappe/utils/urllib.js",
"public/js/frappe/utils/pretty_date.js",
"public/js/frappe/utils/tools.js",
"public/js/frappe/utils/datetime.js",
"public/js/frappe/utils/number_format.js",
"public/js/frappe/utils/help.js",
"public/js/frappe/utils/help_links.js",
"public/js/frappe/utils/address_and_contact.js",
"public/js/frappe/utils/preview_email.js",
"public/js/frappe/utils/file_manager.js",
"public/js/frappe/upload.js",
"public/js/frappe/ui/tree.js",
"public/js/frappe/views/container.js",
"public/js/frappe/views/breadcrumbs.js",
"public/js/frappe/views/factory.js",
"public/js/frappe/views/pageview.js",
"public/js/frappe/ui/toolbar/awesome_bar.js",
"public/js/frappe/ui/toolbar/energy_points_notifications.js",
"public/js/frappe/ui/notifications/notifications.js",
"public/js/frappe/ui/toolbar/search.js",
"public/js/frappe/ui/toolbar/tag_utils.js",
"public/js/frappe/ui/toolbar/search.html",
"public/js/frappe/ui/toolbar/search_utils.js",
"public/js/frappe/ui/toolbar/about.js",
"public/js/frappe/ui/toolbar/navbar.html",
"public/js/frappe/ui/toolbar/toolbar.js",
"public/js/frappe/ui/toolbar/notifications.js",
"public/js/frappe/views/communication.js",
"public/js/frappe/views/translation_manager.js",
"public/js/frappe/views/workspace/workspace.js",
"public/js/frappe/widgets/widget_group.js",
"public/js/frappe/ui/sort_selector.html",
"public/js/frappe/ui/sort_selector.js",
"public/js/frappe/change_log.html",
"public/js/frappe/ui/workspace_loading_skeleton.html",
"public/js/frappe/desk.js",
"public/js/frappe/query_string.js",
"public/js/frappe/ui/comment.js",
"public/js/frappe/chat.js",
"public/js/frappe/utils/energy_point_utils.js",
"public/js/frappe/utils/dashboard_utils.js",
"public/js/frappe/ui/chart.js",
"public/js/frappe/ui/datatable.js",
"public/js/frappe/ui/driver.js",
"public/js/frappe/ui/plyr.js",
"public/js/frappe/barcode_scanner/index.js"
],
"js/form.min.js": [
"public/js/frappe/form/templates/**.html",
"public/js/frappe/form/controls/control.js",
"public/js/frappe/views/formview.js",
"public/js/frappe/form/form.js",
"public/js/frappe/meta_tag.js"
],
"js/list.min.js": [
"public/js/frappe/ui/listing.html",
"public/js/frappe/model/indicator.js",
"public/js/frappe/ui/filters/filter.js",
"public/js/frappe/ui/filters/filter_list.js",
"public/js/frappe/ui/filters/field_select.js",
"public/js/frappe/ui/filters/edit_filter.html",
"public/js/frappe/ui/tags.js",
"public/js/frappe/ui/tag_editor.js",
"public/js/frappe/ui/like.js",
"public/js/frappe/ui/liked_by.html",
"public/html/print_template.html",
"public/js/frappe/list/base_list.js",
"public/js/frappe/list/list_view.js",
"public/js/frappe/list/list_factory.js",
"public/js/frappe/list/list_view_select.js",
"public/js/frappe/list/list_sidebar.js",
"public/js/frappe/list/list_sidebar.html",
"public/js/frappe/list/list_sidebar_stat.html",
"public/js/frappe/list/list_sidebar_group_by.js",
"public/js/frappe/list/list_view_permission_restrictions.html",
"public/js/frappe/views/gantt/gantt_view.js",
"public/js/frappe/views/calendar/calendar.js",
"public/js/frappe/views/dashboard/dashboard_view.js",
"public/js/frappe/views/image/image_view.js",
"public/js/frappe/views/map/map_view.js",
"public/js/frappe/views/kanban/kanban_view.js",
"public/js/frappe/views/inbox/inbox_view.js",
"public/js/frappe/views/file/file_view.js",
"public/js/frappe/views/treeview.js",
"public/js/frappe/views/interaction.js",
"public/js/frappe/views/image/image_view_item_row.html",
"public/js/frappe/views/image/photoswipe_dom.html",
"public/js/frappe/views/kanban/kanban_board.html",
"public/js/frappe/views/kanban/kanban_column.html",
"public/js/frappe/views/kanban/kanban_card.html"
],
"css/report.min.css": [
"node_modules/frappe-datatable/dist/frappe-datatable.css",
"public/css/tree_grid.css"
],
"js/report.min.js": [
"public/js/lib/clusterize.min.js",
"public/js/frappe/views/reports/report_factory.js",
"public/js/frappe/views/reports/report_view.js",
"public/js/frappe/views/reports/query_report.js",
"public/js/frappe/views/reports/print_grid.html",
"public/js/frappe/views/reports/print_tree.html",
"public/js/frappe/ui/group_by/group_by.html",
"public/js/frappe/ui/group_by/group_by.js",
"public/js/frappe/views/reports/report_utils.js"
],
"js/web_form.min.js": [
"public/js/frappe/utils/datetime.js",
"public/js/frappe/web_form/webform_script.js"
],
"css/web_form.css": [
"website/css/web_form.css",
"public/css/octicons/octicons.css",
"public/scss/controls.scss",
"node_modules/frappe-datatable/dist/frappe-datatable.css"
],
"css/email.css": "public/scss/email.scss",
"js/barcode_scanner.min.js": "public/js/frappe/barcode_scanner/quagga.js",
"js/user_profile_controller.min.js": "desk/page/user_profile/user_profile_controller.js",
"css/login.css": "public/scss/login.scss",
"js/data_import_tools.min.js": "public/js/frappe/data_import/index.js"
}

File diff suppressed because it is too large Load diff

View file

@ -1,118 +0,0 @@
.navbar .navbar-search-icon{
right: auto;
left: 24px;
}
.navbar > .container > .navbar-header{
float: right !important;
}
body[data-sidebar="0"] .navbar-home {
margin-left: auto !important;
margin-right: 15px !important;
}
.navbar-desk ~ ul > li {
float: right !important;
}
body.no-breadcrumbs .navbar .navbar-home:before {
margin-right: auto;
margin-left: 10px !important;
-ms-transform:rotate(180deg); /* Internet Explorer 9 */
-webkit-transform:rotate(180deg); /* Chrome, Safari, Opera */
transform:rotate(180deg); /* Standard syntax */
}
.layout-side-section .overlay-sidebar {
left: auto !important;
right: 0 !important;
}
.layout-side-section .overlay-sidebar.opened {
transform:translateX(0) !important;
}
.navbar-right {
float: left !important;
}
#navbar-breadcrumbs > li > a:before {
margin-right: auto;
margin-left: 10px;
top: 6px;
-ms-transform:rotate(180deg); /* Internet Explorer 9 */
-webkit-transform:rotate(180deg); /* Chrome, Safari, Opera */
transform:rotate(180deg); /* Standard syntax */
}
.case-wrapper {
float: right;
}
.link-btn {
right: auto;
left: 4px;
transform:rotate(180deg); /* Rotate icon*/
}
.sidebar-menu .badge {
right: auto;
left: 0px;
}
.indicator::before {
margin: 0 0 0 4px;
}
.pull-left {
float: right !important;
}
.grid-row > .row .col:last-child {
margin-right: auto;
margin-left: -10px;
}
.text-right {
text-align: left;
}
.list-row-head .octicon-heart {
margin-right: auto;
margin-left: 13px;
}
.list-id {
margin-left: 7px !important;
}
.avatar-small .avatar-sm {
margin-left: 5px;
margin-right: auto;
}
.list-row-right .list-row-modified {
margin-right: auto;
margin-left: 9px;
}
.list-comment-count {
text-align: right;
}
ul.tree-children {
padding-right: 20px;
padding-left: inherit !important;
}
.balance-area {
float: left !important;
}
.tree.opened::before, .tree-node.opened::before, .tree:last-child::after, .tree-node:last-child::after {
left: inherit !important;
right: 8px;
}
.tree.opened > .tree-children > .tree-node > .tree-link::before, .tree-node.opened > .tree-children > .tree-node > .tree-link::before {
left: inherit !important;
right: -11px;
}
.tree:last-child::after, .tree-node:last-child::after {
right: -13px !important;
}
.tree.opened::before {
left: auto !important;
right: 23px;
}
.results {
direction: ltr;
}
.data-table {
direction: ltr;
}
.section-header {
direction: ltr;
}
.ql-editor {
direction: rtl;
text-align: right;
}

View file

@ -1,15 +0,0 @@
.grid-report {
direction: ltr;
}
.page-form .awesomplete > ul {
left: auto;
}
.chart_area{
direction: ltr;
}
.grid-report .show-zero{
direction: rtl;
}

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en">
<html lang="{{ lang }}" dir="{{ layout_direction }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">

View file

@ -168,9 +168,13 @@ frappe.assets = {
}
},
bundled_asset(path) {
bundled_asset(path, is_rtl=null) {
if (!path.startsWith('/assets') && path.includes('.bundle.')) {
return frappe.boot.assets_json[path] || path;
if (path.endsWith('.css') && is_rtl) {
path = `rtl_${path}`;
}
path = frappe.boot.assets_json[path] || path;
return path;
}
return path;
}

View file

@ -64,8 +64,6 @@ frappe.Application = class Application {
}
});
this.set_rtl();
// page container
this.make_page_container();
this.set_route();
@ -489,16 +487,6 @@ frappe.Application = class Application {
}, 100);
}
set_rtl() {
if (frappe.utils.is_rtl()) {
var ls = document.createElement('link');
ls.rel="stylesheet";
ls.type = "text/css";
ls.href= frappe.assets.bundled_asset("frappe-rtl.bundle.css");
document.getElementsByTagName('head')[0].appendChild(ls);
$('body').addClass('frappe-rtl');
}
}
show_change_log() {
var me = this;

View file

@ -1264,7 +1264,9 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
print_css: print_css,
print_settings: print_settings,
landscape: landscape,
columns: columns
columns: columns,
lang: frappe.boot.lang,
layout_direction: frappe.utils.is_rtl() ? "rtl" : "ltr"
});
frappe.render_pdf(html, print_settings);

View file

@ -4,7 +4,7 @@
background-color: white;
font-size: var(--text-sm);
}
/*! This comment will be included even in compressed mode. */
#navbar-breadcrumbs {
margin-left: var(--margin-md);
font-size: var(--text-sm);
@ -12,7 +12,7 @@
font-size: var(--text-md);
margin-right: 10px;
&:before {
content: var(--right-arrow-svg);
content: #{"/*!rtl:var(--left-arrow-svg);*/"}var(--right-arrow-svg);
display: inline-block;
margin-right: 10px;
}

View file

@ -64,4 +64,6 @@ $input-height: 28px !default;
--skeleton-bg: var(--gray-100);
--right-arrow-svg: url("data: image/svg+xml;utf8, <svg width='6' height='8' viewBox='0 0 6 8' fill='none' xmlns='http://www.w3.org/2000/svg'><path d='M1.25 7.5L4.75 4L1.25 0.5' stroke='%231F272E' stroke-linecap='round' stroke-linejoin='round'/></svg>");
--left-arrow-svg: url("data: image/svg+xml;utf8, <svg width='6' height='8' viewBox='0 0 6 8' fill='none' xmlns='http://www.w3.org/2000/svg'><path d='M7.5 9.5L4 6l3.5-3.5' stroke='%231F272E' stroke-linecap='round' stroke-linejoin='round'></path></svg>");
}

View file

@ -157,4 +157,6 @@
--skeleton-bg: var(--gray-800);
--right-arrow-svg: url("data: image/svg+xml;utf8, <svg width='6' height='8' viewBox='0 0 6 8' fill='none' xmlns='http://www.w3.org/2000/svg'><path d='M1.25 7.5L4.75 4L1.25 0.5' stroke='white' stroke-linecap='round' stroke-linejoin='round'/></svg>");
--left-arrow-svg: url("data: image/svg+xml;utf8, <svg width='6' height='8' viewBox='0 0 6 8' fill='none' xmlns='http://www.w3.org/2000/svg'><path d='M7.5 9.5L4 6l3.5-3.5' stroke='white' stroke-linecap='round' stroke-linejoin='round'></path></svg>");
}

View file

@ -574,3 +574,15 @@ details > summary:focus {
// font-family: 'Octicons';
// content: "\f00b";
// }
/*rtl:raw:
.dropdown-menu {
right: auto;
}
.popover {
right: auto;
}
.chart-container {
direction: ltr;
}
*/

View file

@ -1,3 +0,0 @@
@import "frappe/public/css/bootstrap-rtl.css";
@import "frappe/public/css/desk-rtl.css";
@import "frappe/public/css/report-rtl.css";

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<html>
<html lang={{ lang }} dir={{ layout_direction }}>
<head>
<meta charset="utf-8">

View file

@ -73,17 +73,25 @@ def include_script(path):
return f'<script type="text/javascript" src="{path}"></script>'
def include_style(path):
def include_style(path, rtl=None):
path = bundled_asset(path)
return f'<link type="text/css" rel="stylesheet" href="{path}">'
def bundled_asset(path):
def bundled_asset(path, rtl=None):
from frappe.utils import get_assets_json
from frappe.website.utils import abs_url
if ".bundle." in path and not path.startswith("/assets"):
bundled_assets = get_assets_json()
if path.endswith('.css') and is_rtl(rtl):
path = f"rtl_{path}"
path = bundled_assets.get(path) or path
return abs_url(path)
def is_rtl(rtl=None):
from frappe import local
if rtl is None:
return local.lang in ["ar", "he", "fa", "ps"]
return rtl

View file

@ -13,7 +13,7 @@ from PyPDF2 import PdfFileReader, PdfFileWriter
import frappe
from frappe import _
from frappe.utils import scrub_urls
from frappe.utils.jinja_globals import bundled_asset
from frappe.utils.jinja_globals import bundled_asset, is_rtl
PDF_CONTENT_ERRORS = ["ContentNotFoundError", "ContentOperationNotPermittedError",
"UnknownContentError", "RemoteHostClosedError"]
@ -177,7 +177,9 @@ def prepare_header_footer(soup):
"content": content,
"styles": styles,
"html_id": html_id,
"css": css
"css": css,
"lang": frappe.local.lang,
"layout_direction": "rtl" if is_rtl else "ltr"
})
# create temp file

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<html data-theme="{{ desk_theme.lower() }}">
<html data-theme="{{ desk_theme.lower() }}" dir={{ layout_direction }} lang="{{ lang }}">
<head>
<!-- Chrome, Firefox OS and Opera -->
<meta name="theme-color" content="#0089FF">

View file

@ -6,6 +6,7 @@ import os, re
import frappe
from frappe import _
import frappe.sessions
from frappe.utils.jinja_globals import is_rtl
def get_context(context):
if frappe.session.user == "Guest":
@ -40,6 +41,8 @@ def get_context(context):
"build_version": frappe.utils.get_build_version(),
"include_js": hooks["app_include_js"],
"include_css": hooks["app_include_css"],
"layout_direction": "rtl" if is_rtl() else "ltr",
"lang": frappe.local.lang,
"sounds": hooks["sounds"],
"boot": boot if context.get("for_mobile") else boot_json,
"desk_theme": desk_theme or "Light",

View file

@ -1,14 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<html lang="{{ lang }}" dir="{{ layout_direction }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ title }}</title>
<meta name="generator" content="frappe">
{{ include_style('print.bundle.css') }}
{%- if has_rtl -%}
{{ include_style('frappe-rtl.bundle.css') }}
{%- endif -%}
<style>
{{ css }}
</style>

View file

@ -7,6 +7,7 @@ from frappe import _
from frappe.modules import get_doc_path
from frappe.core.doctype.access_log.access_log import make_access_log
from frappe.utils import cint, sanitize_html, strip_html
from frappe.utils.jinja_globals import is_rtl
no_cache = 1
@ -44,7 +45,8 @@ def get_context(context):
"css": get_print_style(frappe.form_dict.style, print_format),
"comment": frappe.session.user,
"title": doc.get(meta.title_field) if meta.title_field else doc.name,
"has_rtl": True if frappe.local.lang in ["ar", "he", "fa", "ps"] else False
"lang": frappe.local.lang,
"layout_direction": "rtl" if is_rtl() else "ltr"
}
def get_print_format_doc(print_format_name, meta):

View file

@ -67,6 +67,7 @@
"fast-glob": "^3.2.5",
"launch-editor": "^2.2.1",
"md5": "^2.3.0",
"rtlcss": "^3.2.1",
"yargs": "^16.2.0"
},
"snyk": true

View file

@ -2413,6 +2413,14 @@ find-up@^3.0.0:
dependencies:
locate-path "^3.0.0"
find-up@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
dependencies:
locate-path "^6.0.0"
path-exists "^4.0.0"
follow-redirects@^1.10.0:
version "1.13.3"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.3.tgz#e5598ad50174c1bc4e872301e82ac2cd97f90267"
@ -3690,6 +3698,13 @@ locate-path@^3.0.0:
p-locate "^3.0.0"
path-exists "^3.0.0"
locate-path@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==
dependencies:
p-locate "^5.0.0"
lodash.assign@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7"
@ -4222,6 +4237,11 @@ nanoid@^3.1.22:
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.22.tgz#b35f8fb7d151990a8aebd5aa5015c03cf726f844"
integrity sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ==
nanoid@^3.1.23:
version "3.1.23"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81"
integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==
native-request@^1.0.5:
version "1.0.8"
resolved "https://registry.yarnpkg.com/native-request/-/native-request-1.0.8.tgz#8f66bf606e0f7ea27c0e5995eb2f5d03e33ae6fb"
@ -4571,6 +4591,13 @@ p-limit@^2.0.0:
dependencies:
p-try "^2.0.0"
p-limit@^3.0.2:
version "3.1.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
dependencies:
yocto-queue "^0.1.0"
p-locate@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
@ -4578,6 +4605,13 @@ p-locate@^3.0.0:
dependencies:
p-limit "^2.0.0"
p-locate@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
dependencies:
p-limit "^3.0.2"
p-map@2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175"
@ -4700,6 +4734,11 @@ path-exists@^3.0.0:
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=
path-exists@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
path-is-absolute@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
@ -5158,6 +5197,15 @@ postcss@^7.0.32:
source-map "^0.6.1"
supports-color "^6.1.0"
postcss@^8.2.4:
version "8.3.5"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.5.tgz#982216b113412bc20a86289e91eb994952a5b709"
integrity sha512-NxTuJocUhYGsMiMFHDUkmjSKT3EdH4/WbGF6GCi1NDGk+vbcUTun4fpbOqaPtD8IIsztA2ilZm2DhYCuyN58gA==
dependencies:
colorette "^1.2.2"
nanoid "^3.1.23"
source-map-js "^0.6.2"
prepend-http@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897"
@ -5840,6 +5888,17 @@ roarr@^2.15.3:
semver-compare "^1.0.0"
sprintf-js "^1.1.2"
rtlcss@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/rtlcss/-/rtlcss-3.2.1.tgz#654e55ea2f46991f9738d952ba77ba0aa94a670d"
integrity sha512-S9bh35JXwPIhfun7nFu/HjlNrwELL5nvTJqA1suLfbnqY/mauIL5sBkrJNHziVppX9PA2rJ7NV82+RtzB71mJA==
dependencies:
chalk "^4.1.0"
find-up "^5.0.0"
mkdirp "^1.0.4"
postcss "^8.2.4"
strip-json-comments "^3.1.1"
run-async@^2.4.0:
version "2.4.1"
resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
@ -6447,6 +6506,11 @@ sortablejs@^1.7.0:
resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.8.3.tgz#5ae908ef96300966e95440a143340f5dd565a0df"
integrity sha512-AftvD4hdKcR5QlGi7L/JST506zGNGrysE8/QohDpwKXJarHWqCt+TUlrtoMk/wkECB607Q019/OZlJViyWiD6A==
source-map-js@^0.6.2:
version "0.6.2"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e"
integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==
source-map-resolve@^0.5.2:
version "0.5.3"
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"
@ -6744,6 +6808,11 @@ strip-indent@^1.0.1:
dependencies:
get-stdin "^4.0.1"
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"
@ -7556,3 +7625,8 @@ yeast@0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"
integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk=
yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==