diff --git a/services/cms/src/components/editors/GutenbergEditor.tsx b/services/cms/src/components/editors/GutenbergEditor.tsx index a1a700bc5685..86f7ab7d8f85 100644 --- a/services/cms/src/components/editors/GutenbergEditor.tsx +++ b/services/cms/src/components/editors/GutenbergEditor.tsx @@ -103,6 +103,7 @@ const GutenbergEditor: React.FC> = >({ disableCustomColors: false, disableCustomEditorFontSizes: false, + styles: [], }) const sideBarStartingYCoordinate = useSidebarStartingYCoodrinate() diff --git a/services/cms/src/styles/Gutenberg/editor-styles.scss b/services/cms/src/styles/Gutenberg/editor-styles.scss index 6353b34043ca..9d5eeb310dd9 100644 --- a/services/cms/src/styles/Gutenberg/editor-styles.scss +++ b/services/cms/src/styles/Gutenberg/editor-styles.scss @@ -129,3 +129,7 @@ .wp-block-embed .components-placeholder__learn-more { display: none; } + +.block-editor-plain-text { + width: 100%; +} diff --git a/services/course-material/src/components/ContentRenderer/core/formatting/CodeBlock/SyntaxHighlightedContainer.tsx b/services/course-material/src/components/ContentRenderer/core/formatting/CodeBlock/SyntaxHighlightedContainer.tsx index 1266056c43fc..2fe3027b6538 100644 --- a/services/course-material/src/components/ContentRenderer/core/formatting/CodeBlock/SyntaxHighlightedContainer.tsx +++ b/services/course-material/src/components/ContentRenderer/core/formatting/CodeBlock/SyntaxHighlightedContainer.tsx @@ -21,7 +21,9 @@ const SyntaxHighlightedContainer: React.FC = ({ // The content coming from gutenberg contains
tags which do not work when we higlight the code with hljs // So we'll replace the br tags with newlines const replacedContent = useMemo(() => { - return content?.replace(//g, "\n") ?? "" + let res = content ?? "" + res = res.replace(//g, "\n") + return res }, [content]) return ( @@ -29,6 +31,7 @@ const SyntaxHighlightedContainer: React.FC = ({ className={css` background-color: #1a2333; border-radius: 4px; + font-variant-ligatures: none; `} ref={ref} dangerouslySetInnerHTML={{ __html: sanitizeCourseMaterialHtml(replacedContent) }} diff --git a/services/course-material/src/components/ContentRenderer/core/formatting/CodeBlock/index.tsx b/services/course-material/src/components/ContentRenderer/core/formatting/CodeBlock/index.tsx index eba3f7209395..92432f114290 100644 --- a/services/course-material/src/components/ContentRenderer/core/formatting/CodeBlock/index.tsx +++ b/services/course-material/src/components/ContentRenderer/core/formatting/CodeBlock/index.tsx @@ -1,9 +1,9 @@ import { css } from "@emotion/css" import dynamic from "next/dynamic" +import { useMemo } from "react" import { BlockRendererProps } from "../../.." import { CodeAttributes } from "../../../../../../types/GutenbergBlockAttributes" -import { fontSizeMapper } from "../../../../../styles/fontSizeMapper" import BreakFromCentered from "@/shared-module/common/components/Centering/BreakFromCentered" import Spinner from "@/shared-module/common/components/Spinner" @@ -19,15 +19,36 @@ const SyntaxHighlightedContainer = dynamic(() => import("./SyntaxHighlightedCont const CodeBlock: React.FC>> = ({ data, + dontAllowBlockToBeWiderThanContainerWidth, }) => { - const { anchor, content, fontSize } = data.attributes + const { anchor, content } = data.attributes + const fontSizePx = useMemo(() => { + const longestLine = (content ?? "") + .split("\n") + .reduce((acc, line) => (line.length > acc ? line.length : acc), 0) + + let fontSizePx = 20 + if (longestLine > 70) { + fontSizePx = 16 + } + if (longestLine > 100) { + fontSizePx = 14 + } + return fontSizePx + }, [content]) + return ( - +
 {
-  const sanitizedHTML = sanitizeCourseMaterialHtml(content)
-  const { count, converted: parsedLatex } = convertToLatex(sanitizedHTML)
+  const { count, converted: parsedLatex } = convertToLatex(content ?? "")
   const parsedCitation = parseCitation(parsedLatex)
 
   let parsedText = parsedCitation
diff --git a/services/headless-lms/Cargo.lock b/services/headless-lms/Cargo.lock
index bae61390c6c2..c84c52886125 100644
--- a/services/headless-lms/Cargo.lock
+++ b/services/headless-lms/Cargo.lock
@@ -557,6 +557,12 @@ version = "0.21.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
 
+[[package]]
+name = "base64"
+version = "0.22.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
+
 [[package]]
 name = "base64ct"
 version = "1.6.0"
@@ -1242,14 +1248,14 @@ version = "0.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6a595cb550439a117696039dfc69830492058211b771a2a165379f2a1a53d84d"
 dependencies = [
- "roxmltree",
+ "roxmltree 0.19.0",
 ]
 
 [[package]]
 name = "fontdb"
-version = "0.16.2"
+version = "0.18.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0299020c3ef3f60f526a4f64ab4a3d4ce116b1acbf24cdd22da0068e5d81dc3"
+checksum = "e32eac81c1135c1df01d4e6d4233c47ba11f6a6d07f33e0bba09d18797077770"
 dependencies = [
  "fontconfig-parser",
  "log",
@@ -1424,9 +1430,9 @@ dependencies = [
 
 [[package]]
 name = "gif"
-version = "0.12.0"
+version = "0.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045"
+checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2"
 dependencies = [
  "color_quant",
  "weezl",
@@ -2439,11 +2445,12 @@ dependencies = [
 
 [[package]]
 name = "kurbo"
-version = "0.9.5"
+version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd85a5776cd9500c2e2059c8c76c3b01528566b7fcbaf8098b55a33fc298849b"
+checksum = "6e5aa9f0f96a938266bdb12928a67169e8d22c6a786fda8ed984b85e6ba93c3c"
 dependencies = [
  "arrayvec",
+ "smallvec",
 ]
 
 [[package]]
@@ -3122,9 +3129,9 @@ dependencies = [
 
 [[package]]
 name = "quick-xml"
-version = "0.31.0"
+version = "0.35.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33"
+checksum = "86e446ed58cef1bbfe847bc2fda0e2e4ea9f0e57b90c507d4781292590d72a4e"
 dependencies = [
  "memchr",
 ]
@@ -3352,15 +3359,14 @@ dependencies = [
 
 [[package]]
 name = "resvg"
-version = "0.38.0"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c34501046959e06470ba62a2dc7f31c15f94ac250d842a45f9e012f4ee40c1e"
+checksum = "944d052815156ac8fa77eaac055220e95ba0b01fa8887108ca710c03805d9051"
 dependencies = [
  "gif",
  "jpeg-decoder",
  "log",
  "pico-args",
- "png",
  "rgb",
  "svgtypes",
  "tiny-skia",
@@ -3412,6 +3418,12 @@ version = "0.19.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3cd14fd5e3b777a7422cca79358c57a8f6e3a703d9ac187448d0daf220c2407f"
 
+[[package]]
+name = "roxmltree"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97"
+
 [[package]]
 name = "rsa"
 version = "0.9.6"
@@ -3493,9 +3505,9 @@ dependencies = [
 
 [[package]]
 name = "rustybuzz"
-version = "0.12.1"
+version = "0.14.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0ae5692c5beaad6a9e22830deeed7874eae8a4e3ba4076fb48e12c56856222c"
+checksum = "cfb9cf8877777222e4a3bc7eb247e398b56baba500c38c1c46842431adc8b55c"
 dependencies = [
  "bitflags 2.4.2",
  "bytemuck",
@@ -3728,9 +3740,9 @@ dependencies = [
 
 [[package]]
 name = "siphasher"
-version = "0.3.11"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
+checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
 
 [[package]]
 name = "slab"
@@ -4076,9 +4088,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
 
 [[package]]
 name = "svgtypes"
-version = "0.13.0"
+version = "0.15.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e44e288cd960318917cbd540340968b90becc8bc81f171345d706e7a89d9d70"
+checksum = "fae3064df9b89391c9a76a0425a69d124aee9c5c28455204709e72c39868a43c"
 dependencies = [
  "kurbo",
  "siphasher",
@@ -4485,9 +4497,9 @@ dependencies = [
 
 [[package]]
 name = "ttf-parser"
-version = "0.20.0"
+version = "0.21.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4"
+checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8"
 
 [[package]]
 name = "typenum"
@@ -4512,15 +4524,15 @@ checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
 
 [[package]]
 name = "unicode-bidi-mirroring"
-version = "0.1.0"
+version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56d12260fb92d52f9008be7e4bca09f584780eb2266dc8fecc6a192bec561694"
+checksum = "23cb788ffebc92c5948d0e997106233eeb1d8b9512f93f41651f52b6c5f5af86"
 
 [[package]]
 name = "unicode-ccc"
-version = "0.1.2"
+version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc2520efa644f8268dce4dcd3050eaa7fc044fca03961e9998ac7e2e92b77cf1"
+checksum = "1df77b101bcc4ea3d78dafc5ad7e4f58ceffe0b2b16bf446aeb50b6cb4157656"
 
 [[package]]
 name = "unicode-ident"
@@ -4609,62 +4621,29 @@ checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
 
 [[package]]
 name = "usvg"
-version = "0.38.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "377f62b4a3c173de8654c1aa80ab1dac1154e6f13a779a9943e53780120d1625"
-dependencies = [
- "base64 0.21.7",
- "log",
- "pico-args",
- "usvg-parser",
- "usvg-text-layout",
- "usvg-tree",
- "xmlwriter",
-]
-
-[[package]]
-name = "usvg-parser"
-version = "0.38.0"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "351a05e6f2023d6b4e946f734240a3927aefdcf930d7d42587a2c8a8869814b0"
+checksum = "b84ea542ae85c715f07b082438a4231c3760539d902e11d093847a0b22963032"
 dependencies = [
+ "base64 0.22.1",
  "data-url",
  "flate2",
+ "fontdb",
  "imagesize",
  "kurbo",
  "log",
- "roxmltree",
+ "pico-args",
+ "roxmltree 0.20.0",
+ "rustybuzz",
  "simplecss",
  "siphasher",
+ "strict-num",
  "svgtypes",
- "usvg-tree",
-]
-
-[[package]]
-name = "usvg-text-layout"
-version = "0.38.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c41888b9d5cf431fe852eaf9d047bbde83251b98f1749c2f08b1071e6db46e2"
-dependencies = [
- "fontdb",
- "kurbo",
- "log",
- "rustybuzz",
+ "tiny-skia-path",
  "unicode-bidi",
  "unicode-script",
  "unicode-vo",
- "usvg-tree",
-]
-
-[[package]]
-name = "usvg-tree"
-version = "0.38.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18863e0404ed153d6e56362c5b1146db9f4f262a3244e3cf2dbe7d8a85909f05"
-dependencies = [
- "strict-num",
- "svgtypes",
- "tiny-skia-path",
+ "xmlwriter",
 ]
 
 [[package]]
diff --git a/services/headless-lms/certificates/Cargo.toml b/services/headless-lms/certificates/Cargo.toml
index 749948c4b29a..a4a2722b419c 100644
--- a/services/headless-lms/certificates/Cargo.toml
+++ b/services/headless-lms/certificates/Cargo.toml
@@ -11,13 +11,13 @@ headless-lms-utils = { path = "../utils" }
 headless-lms-models = { path = "../models" }
 
 # An SVG rendering library.
-resvg = "0.38.0"
+resvg = "0.42.0"
 # An SVG simplification library.
-usvg = "0.38.0"
+usvg = "0.42.0"
 # A simple, streaming XML writer.
 xmlwriter = "0.1.0"
 # High performance xml reader and writer
-quick-xml = "0.31.0"
+quick-xml = "0.35.0"
 # International Components for Unicode
 icu = { version = "1.3.2", features = ["std", "serde"] }
 # Trait and struct definitions for the ICU data provider
diff --git a/services/headless-lms/certificates/src/lib.rs b/services/headless-lms/certificates/src/lib.rs
index b226a0e1e6d4..c5b6359c884c 100644
--- a/services/headless-lms/certificates/src/lib.rs
+++ b/services/headless-lms/certificates/src/lib.rs
@@ -15,9 +15,9 @@ use headless_lms_utils::prelude::{UtilError, UtilErrorType, UtilResult};
 use icu::calendar::Gregorian;
 use icu::datetime::TypedDateTimeFormatter;
 use resvg::tiny_skia;
-use std::path::Path;
-use std::time::Instant;
-use usvg::{fontdb, TreeParsing, TreePostProc};
+use std::{io, path::Path};
+use std::{sync::Arc, time::Instant};
+use usvg::fontdb;
 
 use quick_xml::{events::BytesText, Writer};
 use std::io::Cursor;
@@ -121,7 +121,7 @@ pub async fn generate_certificate(
         &texts_to_render,
         &paper_size,
         debug,
-        &fontdb,
+        Arc::new(fontdb),
     )?;
     Ok(res)
 }
@@ -132,7 +132,7 @@ fn generate_certificate_impl(
     texts: &[TextToRender],
     paper_size: &PaperSize,
     debug_show_anchoring_points: bool,
-    fontdb: &fontdb::Database,
+    fontdb: Arc,
 ) -> UtilResult> {
     let start_setup = Instant::now();
     let opt = usvg::Options {
@@ -141,6 +141,7 @@ fn generate_certificate_impl(
         image_rendering: usvg::ImageRendering::OptimizeQuality,
         shape_rendering: usvg::ShapeRendering::GeometricPrecision,
         text_rendering: usvg::TextRendering::OptimizeLegibility,
+        fontdb,
         ..Default::default()
     };
 
@@ -154,22 +155,13 @@ fn generate_certificate_impl(
     })?;
     info!("Setup time {:?}", start_setup.elapsed());
     let parse_background_svg_start = Instant::now();
-    let tree = {
-        let mut tree = usvg::Tree::from_data(background_svg, &opt).map_err(|original_error| {
-            UtilError::new(
-                UtilErrorType::Other,
-                "Could not parse background svg".to_string(),
-                Some(original_error.into()),
-            )
-        })?;
-        tree.postprocess(
-            usvg::PostProcessingSteps {
-                convert_text_into_paths: true,
-            },
-            fontdb,
-        );
-        tree
-    };
+    let tree = usvg::Tree::from_data(background_svg, &opt).map_err(|original_error| {
+        UtilError::new(
+            UtilErrorType::Other,
+            "Could not parse background svg".to_string(),
+            Some(original_error.into()),
+        )
+    })?;
 
     info!(
         "Parse background svg time {:?}",
@@ -179,7 +171,7 @@ fn generate_certificate_impl(
     let start_render_background = Instant::now();
     // Scaling the background to the paper size, if the aspect ratio is wrong (for example if it does not follow the aspect ratio of A4 paper size), the background will get stretched.
     // If that's the case, the you should fix the background svg.
-    let background_size = tree.size.to_int_size();
+    let background_size = tree.size().to_int_size();
     let x_scale = paper_size.width_px() as f32 / background_size.width() as f32;
     let y_scale = paper_size.height_px() as f32 / background_size.height() as f32;
     info!(
@@ -200,23 +192,13 @@ fn generate_certificate_impl(
     let text_svg_data = generate_text_svg(texts, debug_show_anchoring_points, paper_size)?;
     info!("{}", String::from_utf8_lossy(&text_svg_data));
     let parse_text_svg_start = Instant::now();
-    let text_tree = {
-        let mut text_tree =
-            usvg::Tree::from_data(&text_svg_data, &opt).map_err(|original_error| {
-                UtilError::new(
-                    UtilErrorType::Other,
-                    "Could not parse text svg".to_string(),
-                    Some(original_error.into()),
-                )
-            })?;
-        text_tree.postprocess(
-            usvg::PostProcessingSteps {
-                convert_text_into_paths: true,
-            },
-            fontdb,
-        );
-        text_tree
-    };
+    let text_tree = usvg::Tree::from_data(&text_svg_data, &opt).map_err(|original_error| {
+        UtilError::new(
+            UtilErrorType::Other,
+            "Could not parse text svg".to_string(),
+            Some(original_error.into()),
+        )
+    })?;
 
     info!("Parse text svg time {:?}", parse_text_svg_start.elapsed());
 
@@ -230,24 +212,13 @@ fn generate_certificate_impl(
 
     if let Some(overlay_svg) = overlay_svg {
         let start_render_overlay = Instant::now();
-        let overlay_tree = {
-            let mut overlay_tree =
-                usvg::Tree::from_data(overlay_svg, &opt).map_err(|original_error| {
-                    UtilError::new(
-                        UtilErrorType::Other,
-                        "Could not parse overlay svg".to_string(),
-                        Some(original_error.into()),
-                    )
-                })?;
-            overlay_tree.postprocess(
-                usvg::PostProcessingSteps {
-                    convert_text_into_paths: true,
-                },
-                fontdb,
-            );
-            overlay_tree
-        };
-
+        let overlay_tree = usvg::Tree::from_data(overlay_svg, &opt).map_err(|original_error| {
+            UtilError::new(
+                UtilErrorType::Other,
+                "Could not parse overlay svg".to_string(),
+                Some(original_error.into()),
+            )
+        })?;
         resvg::render(
             &overlay_tree,
             tiny_skia::Transform::default(),
@@ -369,7 +340,10 @@ fn generate_text_svg(
                     .write_text_content(BytesText::from_escaped(&text.text))
                     .map_err(|_original_error| {
                         // Might not be optimal but that's the Error type of the closure that comes from the library and we don't want to unwrap here and potentially crash the process.
-                        quick_xml::Error::UnexpectedToken("Could not write text to svg".to_string())
+                        quick_xml::Error::Io(Arc::new(io::Error::new(
+                            io::ErrorKind::Other,
+                            "Could not write text to svg".to_string(),
+                        )))
                     })?;
 
                 if debug_show_anchoring_points {
@@ -382,9 +356,10 @@ fn generate_text_svg(
                         .write_empty()
                         .map_err(|_original_error| {
                             // Might not be optimal but that's the Error type of the closure that comes from the library and we don't want to unwrap here and potentially crash the process.
-                            quick_xml::Error::UnexpectedToken(
+                            quick_xml::Error::Io(Arc::new(io::Error::new(
+                                io::ErrorKind::Other,
                                 "Could not write debug point to svg".to_string(),
-                            )
+                            )))
                         })?;
                     writer
                         .create_element("circle")
@@ -395,9 +370,10 @@ fn generate_text_svg(
                         .write_empty()
                         .map_err(|_original_error| {
                             // Might not be optimal but that's the Error type of the closure that comes from the library and we don't want to unwrap here and potentially crash the process.
-                            quick_xml::Error::UnexpectedToken(
+                            quick_xml::Error::Io(Arc::new(io::Error::new(
+                                io::ErrorKind::Other,
                                 "Could not write debug point to svg".to_string(),
-                            )
+                            )))
                         })?;
                 }
             }
diff --git a/system-tests/src/__screenshots__/course-material/content-components-render.spec.ts/content-components-renderer-view-desktop-regular.png b/system-tests/src/__screenshots__/course-material/content-components-render.spec.ts/content-components-renderer-view-desktop-regular.png
index c9ce5c7bee61..37c11d2b4895 100644
Binary files a/system-tests/src/__screenshots__/course-material/content-components-render.spec.ts/content-components-renderer-view-desktop-regular.png and b/system-tests/src/__screenshots__/course-material/content-components-render.spec.ts/content-components-renderer-view-desktop-regular.png differ
diff --git a/system-tests/src/__screenshots__/course-material/content-components-render.spec.ts/content-components-renderer-view-mobile-tall.png b/system-tests/src/__screenshots__/course-material/content-components-render.spec.ts/content-components-renderer-view-mobile-tall.png
index 0e1cf857fa03..794871d84139 100644
Binary files a/system-tests/src/__screenshots__/course-material/content-components-render.spec.ts/content-components-renderer-view-mobile-tall.png and b/system-tests/src/__screenshots__/course-material/content-components-render.spec.ts/content-components-renderer-view-mobile-tall.png differ