From 38e1eb8fc7297b4c0580f23160e7a123bd7bf5d9 Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Wed, 11 Dec 2024 11:57:35 +0530 Subject: [PATCH 01/16] feat: markdown parser for lessons --- frontend/package.json | 1 + frontend/src/utils/index.js | 4 + frontend/src/utils/markdownParser.js | 144 +++++++++ frontend/yarn.lock | 418 ++++++++++++++++++++++++++- 4 files changed, 564 insertions(+), 3 deletions(-) create mode 100644 frontend/src/utils/markdownParser.js diff --git a/frontend/package.json b/frontend/package.json index 0fc71fa3..44cbca2a 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -23,6 +23,7 @@ "chart.js": "^4.4.1", "codemirror-editor-vue3": "^2.8.0", "dayjs": "^1.11.6", + "editorjs-md-parser": "^0.0.3", "feather-icons": "^4.28.0", "frappe-ui": "^0.1.89", "lucide-vue-next": "^0.383.0", diff --git a/frontend/src/utils/index.js b/frontend/src/utils/index.js index 173d9f97..d0d9e8a7 100644 --- a/frontend/src/utils/index.js +++ b/frontend/src/utils/index.js @@ -2,6 +2,7 @@ import { toast } from 'frappe-ui' import { useTimeAgo } from '@vueuse/core' import { Quiz } from '@/utils/quiz' import { Upload } from '@/utils/upload' +import { MarkdownParser } from '@/utils/markdownParser' import Header from '@editorjs/header' import Paragraph from '@editorjs/paragraph' import { CodeBox } from '@/utils/code' @@ -12,6 +13,8 @@ import dayjs from '@/utils/dayjs' import Embed from '@editorjs/embed' import SimpleImage from '@editorjs/simple-image' import Table from '@editorjs/table' +import MDParser from 'editorjs-md-parser' +import MDImporter from 'editorjs-md-parser' export function createToast(options) { toast({ @@ -150,6 +153,7 @@ export function getEditorTools() { header: Header, quiz: Quiz, upload: Upload, + markdownParser: MarkdownParser, image: SimpleImage, table: Table, paragraph: { diff --git a/frontend/src/utils/markdownParser.js b/frontend/src/utils/markdownParser.js new file mode 100644 index 00000000..2d8dbcb9 --- /dev/null +++ b/frontend/src/utils/markdownParser.js @@ -0,0 +1,144 @@ +export class MarkdownParser { + constructor({ data, api, readOnly, config }) { + console.log('markdownParser constructor called') + this.api = api + this.data = data || {} + this.config = config || {} + this.text = this.data.text || '' + this.readOnly = readOnly + } + + static get toolbox() { + const app = createApp({ + render: () => + h(UploadIcon, { size: 18, strokeWidth: 1.5, color: 'black' }), + }) + + const div = document.createElement('div') + app.mount(div) + + return { + title: 'Upload', + icon: div.innerHTML, + } + } + + static get isReadOnlySupported() { + return true + } + + render() { + console.log(' render() called') + const container = document.createElement('div') + container.contentEditable = true // Make the div editable like a textarea + container.classList.add('markdown-parser') + container.textContent = this.text + + container.addEventListener('blur', () => { + this.text = container.textContent.trim() + this.parseMarkdown() + }) + + this.textArea = container + return container + } + + save(blockContent) { + return { + text: this.text, + } + } + + /** + * Parse Markdown text and render Editor.js blocks. + */ + parseMarkdown() { + console.log(' parseMarkdown() called') + const markdown = this.text + const lines = markdown.split('\n') + + const blocks = lines.map((line) => { + if (line.startsWith('# ')) { + return { + type: 'header', + data: { text: line.replace('# ', ''), level: 1 }, + } + } else if (line.startsWith('## ')) { + return { + type: 'header', + data: { text: line.replace('## ', ''), level: 2 }, + } + } else if (line.startsWith('- ')) { + return { + type: 'list', + data: { + items: [line.replace('- ', '')], + style: 'unordered', + }, + } + } else if (this.isImage(line)) { + const { alt, url } = this.extractImage(line) + return { + type: 'image', + data: { + file: { url }, + caption: alt, + withBorder: false, + stretched: false, + withBackground: false, + }, + } + } else if (this.isLink(line)) { + const { text, url } = this.extractLink(line) + return { + type: 'linkTool', + data: { link: url, meta: { title: text } }, + } + } else { + return { type: 'paragraph', data: { text: line } } + } + }) + + this.api.blocks.render({ blocks }) + } + + /** + * Check if the line matches the image syntax. + * @param {string} line - The line of text. + * @returns {boolean} + */ + isImage(line) { + return /^!\[.*\]\(.*\)$/.test(line) + } + + /** + * Extract alt text and URL from the image syntax. + * @param {string} line - The line of text. + * @returns {Object} { alt, url } + */ + extractImage(line) { + const match = line.match(/^!\[(.*)\]\((.*)\)$/) + return { alt: match[1], url: match[2] } + } + + /** + * Check if the line matches the link syntax. + * @param {string} line - The line of text. + * @returns {boolean} + */ + isLink(line) { + return /^\[.*\]\(.*\)$/.test(line) + } + + /** + * Extract text and URL from the link syntax. + * @param {string} line - The line of text. + * @returns {Object} { text, url } + */ + extractLink(line) { + const match = line.match(/^\[(.*)\]\((.*)\)$/) + return { text: match[1], url: match[2] } + } +} + +export default MarkdownParser diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 024c42e8..18be4244 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -752,6 +752,11 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== +"@types/json-schema@^7.0.8": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + "@types/linkify-it@^5": version "5.0.0" resolved "https://registry.yarnpkg.com/@types/linkify-it/-/linkify-it-5.0.0.tgz#21413001973106cda1c3a9b91eedd4ccd5469d76" @@ -765,11 +770,23 @@ "@types/linkify-it" "^5" "@types/mdurl" "^2" +"@types/mdast@^3.0.0": + version "3.0.15" + resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.15.tgz#49c524a263f30ffa28b71ae282f813ed000ab9f5" + integrity sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ== + dependencies: + "@types/unist" "^2" + "@types/mdurl@^2": version "2.0.0" resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-2.0.0.tgz#d43878b5b20222682163ae6f897b20447233bdfd" integrity sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg== +"@types/unist@^2", "@types/unist@^2.0.0", "@types/unist@^2.0.2": + version "2.0.11" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.11.tgz#11af57b127e32487774841f7a4e54eab166d03c4" + integrity sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA== + "@types/web-bluetooth@^0.0.20": version "0.0.20" resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz#f066abfcd1cbe66267cdbbf0de010d8a41b41597" @@ -892,6 +909,26 @@ ace-builds@^1.36.2: resolved "https://registry.yarnpkg.com/ace-builds/-/ace-builds-1.36.5.tgz#ae9cc7a32eccc2f484926131c00545cd6b78a6a6" integrity sha512-mZ5KVanRT6nLRDLqtG/1YQQLX/gZVC/v526cm1Ru/MTSlrbweSmqv2ZT0d2GaHpJq035MwCMIrj+LgDAUnDXrg== +ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + +ajv@^6.12.5: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + integrity sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg== + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -944,6 +981,11 @@ aria-hidden@^1.2.4: dependencies: tslib "^2.0.0" +async@~0.2.6: + version "0.2.10" + resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" + integrity sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ== + autoprefixer@^10.4.2: version "10.4.20" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.20.tgz#5caec14d43976ef42e32dcb4bd62878e96be5b3b" @@ -956,11 +998,21 @@ autoprefixer@^10.4.2: picocolors "^1.0.1" postcss-value-parser "^4.2.0" +bail@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" + integrity sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ== + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + binary-extensions@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" @@ -1000,6 +1052,21 @@ caniuse-lite@^1.0.30001646, caniuse-lite@^1.0.30001669: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001686.tgz#0e04b8d90de8753188e93c9989d56cb19d902670" integrity sha512-Y7deg0Aergpa24M3qLC5xjNklnKnhsmSyR/V89dLZ1n0ucJIFNs7PgR2Yfa/Zf6W79SbBicgtGxZr2juHkEUIA== +character-entities-legacy@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" + integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== + +character-entities@^1.0.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" + integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== + +character-reference-invalid@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" + integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== + chart.js@^4.4.1: version "4.4.7" resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-4.4.7.tgz#7a01ee0b4dac3c03f2ab0589af888db296d896fa" @@ -1081,6 +1148,22 @@ cross-spawn@^7.0.0: shebang-command "^2.0.0" which "^2.0.1" +css-loader@^5.0.0: + version "5.2.7" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-5.2.7.tgz#9b9f111edf6fb2be5dc62525644cbc9c232064ae" + integrity sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg== + dependencies: + icss-utils "^5.1.0" + loader-utils "^2.0.0" + postcss "^8.2.15" + postcss-modules-extract-imports "^3.0.0" + postcss-modules-local-by-default "^4.0.0" + postcss-modules-scope "^3.0.0" + postcss-modules-values "^4.0.0" + postcss-value-parser "^4.1.0" + schema-utils "^3.0.0" + semver "^7.3.5" + cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" @@ -1096,6 +1179,13 @@ dayjs@^1.11.6: resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== +debug@^4.0.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" + integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== + dependencies: + ms "^2.1.3" + debug@~4.3.1, debug@~4.3.2: version "4.3.7" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" @@ -1128,6 +1218,17 @@ eastasianwidth@^0.2.0: resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== +editorjs-md-parser@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/editorjs-md-parser/-/editorjs-md-parser-0.0.3.tgz#cd54c6caca72590894eb5c61827b73ecbb557666" + integrity sha512-8ohPGuCoO3oag5wjky+sukP5BV4fEGhnzElxOfoLhpdYrLmMB1uTVgOOlYknoZLozAWOb4cpx1zUS9qVvK0V4g== + dependencies: + css-loader "^5.0.0" + remark "^13.0.0" + remark-parse "^9.0.0" + require "^2.4.20" + style-loader "^2.0.0" + electron-to-chromium@^1.5.41: version "1.5.68" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.68.tgz#4f46be4d465ef00e2100d5557b66f4af70e3ce6c" @@ -1143,6 +1244,11 @@ emoji-regex@^9.2.2: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== + engine.io-client@~6.6.1: version "6.6.2" resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-6.6.2.tgz#e0a09e1c90effe5d6264da1c56d7281998f1e50b" @@ -1208,7 +1314,12 @@ estree-walker@^2.0.2: resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== -fast-deep-equal@^3.1.3: +extend@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== @@ -1224,6 +1335,11 @@ fast-glob@^3.3.2: merge2 "^1.3.0" micromatch "^4.0.4" +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + fastq@^1.6.0: version "1.17.1" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" @@ -1339,11 +1455,29 @@ hasown@^2.0.2: dependencies: function-bind "^1.1.2" +icss-utils@^5.0.0, icss-utils@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" + integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== + idb-keyval@^6.2.0: version "6.2.1" resolved "https://registry.yarnpkg.com/idb-keyval/-/idb-keyval-6.2.1.tgz#94516d625346d16f56f3b33855da11bfded2db33" integrity sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg== +is-alphabetical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" + integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== + +is-alphanumerical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" + integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A== + dependencies: + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" @@ -1351,6 +1485,11 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" +is-buffer@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== + is-core-module@^2.13.0: version "2.15.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.1.tgz#a7363a25bee942fefab0de13bf6aa372c82dcc37" @@ -1358,6 +1497,11 @@ is-core-module@^2.13.0: dependencies: hasown "^2.0.2" +is-decimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" + integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -1375,11 +1519,21 @@ is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-hexadecimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" + integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== + is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-plain-obj@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -1399,6 +1553,16 @@ jiti@^1.21.6: resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.6.tgz#6c7f7398dd4b3142767f9a168af2f317a428d268" integrity sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w== +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json5@^2.1.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + lilconfig@^3.0.0, lilconfig@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.3.tgz#a1bcfd6257f9585bf5ae14ceeebb7b559025e4c4" @@ -1421,6 +1585,15 @@ linkifyjs@^4.1.0: resolved "https://registry.yarnpkg.com/linkifyjs/-/linkifyjs-4.2.0.tgz#9dd30222b9cbabec9c950e725ec00031c7fa3f08" integrity sha512-pCj3PrQyATaoTYKHrgWRF3SJwsm61udVh+vuls/Rl6SptiDhgE7ziUIudAedRY9QEfynmM7/RmLEfPUyw1HPCw== +loader-utils@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c" + integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" + lodash.castarray@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.castarray/-/lodash.castarray-4.4.0.tgz#c02513515e309daddd4c24c60cfddcf5976d9115" @@ -1436,6 +1609,11 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== +longest-streak@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4" + integrity sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg== + lru-cache@^10.2.0: version "10.4.3" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" @@ -1470,6 +1648,34 @@ markdown-it@^14.0.0: punycode.js "^2.3.1" uc.micro "^2.1.0" +mdast-util-from-markdown@^0.8.0: + version "0.8.5" + resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.5.tgz#d1ef2ca42bc377ecb0463a987910dae89bd9a28c" + integrity sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-to-string "^2.0.0" + micromark "~2.11.0" + parse-entities "^2.0.0" + unist-util-stringify-position "^2.0.0" + +mdast-util-to-markdown@^0.6.0: + version "0.6.5" + resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.5.tgz#b33f67ca820d69e6cc527a93d4039249b504bebe" + integrity sha512-XeV9sDE7ZlOQvs45C9UKMtfTcctcaj/pGwH8YLbMHoMOXNNCn2LsqVQOqrF1+/NU8lKDAqozme9SCXWyo9oAcQ== + dependencies: + "@types/unist" "^2.0.0" + longest-streak "^2.0.0" + mdast-util-to-string "^2.0.0" + parse-entities "^2.0.0" + repeat-string "^1.0.0" + zwitch "^1.0.0" + +mdast-util-to-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b" + integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w== + mdurl@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-2.0.0.tgz#80676ec0433025dd3e17ee983d0fe8de5a2237e0" @@ -1480,6 +1686,14 @@ merge2@^1.3.0: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== +micromark@~2.11.0: + version "2.11.4" + resolved "https://registry.yarnpkg.com/micromark/-/micromark-2.11.4.tgz#d13436138eea826383e822449c9a5c50ee44665a" + integrity sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA== + dependencies: + debug "^4.0.0" + parse-entities "^2.0.0" + micromatch@^4.0.4, micromatch@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" @@ -1554,6 +1768,13 @@ object-hash@^3.0.0: resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== +optimist@~0.3.5: + version "0.3.7" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.3.7.tgz#c90941ad59e4273328923074d2cf2e7cbc6ec0d9" + integrity sha512-TCx0dXQzVtSCg2OgY/bO9hjM9cV4XYx09TVK+s3+FhkjT6LovsLe+pPMzpWf+6yXK/hUizs2gUoTw3jHM0VaTQ== + dependencies: + wordwrap "~0.0.2" + orderedmap@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/orderedmap/-/orderedmap-2.1.1.tgz#61481269c44031c449915497bf5a4ad273c512d2" @@ -1564,6 +1785,18 @@ package-json-from-dist@^1.0.0: resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== +parse-entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8" + integrity sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ== + dependencies: + character-entities "^1.0.0" + character-entities-legacy "^1.0.0" + character-reference-invalid "^1.0.0" + is-alphanumerical "^1.0.0" + is-decimal "^1.0.0" + is-hexadecimal "^1.0.0" + path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" @@ -1634,6 +1867,34 @@ postcss-load-config@^4.0.2: lilconfig "^3.0.0" yaml "^2.3.4" +postcss-modules-extract-imports@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz#b4497cb85a9c0c4b5aabeb759bb25e8d89f15002" + integrity sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q== + +postcss-modules-local-by-default@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.1.0.tgz#b0db6bc81ffc7bdc52eb0f84d6ca0bedf0e36d21" + integrity sha512-rm0bdSv4jC3BDma3s9H19ZddW0aHX6EoqwDYU2IfZhRN+53QrufTRo2IdkAbRqLx4R2IYbZnbjKKxg4VN5oU9Q== + dependencies: + icss-utils "^5.0.0" + postcss-selector-parser "^7.0.0" + postcss-value-parser "^4.1.0" + +postcss-modules-scope@^3.0.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz#1bbccddcb398f1d7a511e0a2d1d047718af4078c" + integrity sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA== + dependencies: + postcss-selector-parser "^7.0.0" + +postcss-modules-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" + integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== + dependencies: + icss-utils "^5.0.0" + postcss-nested@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-6.2.0.tgz#4c2d22ab5f20b9cb61e2c5c5915950784d068131" @@ -1657,12 +1918,20 @@ postcss-selector-parser@^6.1.1, postcss-selector-parser@^6.1.2: cssesc "^3.0.0" util-deprecate "^1.0.2" -postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0: +postcss-selector-parser@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz#41bd8b56f177c093ca49435f65731befe25d6b9c" + integrity sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-value-parser@^4.0.0, postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@^8.4.43, postcss@^8.4.47, postcss@^8.4.48, postcss@^8.4.5: +postcss@^8.2.15, postcss@^8.4.43, postcss@^8.4.47, postcss@^8.4.48, postcss@^8.4.5: version "8.4.49" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.49.tgz#4ea479048ab059ab3ae61d082190fabfd994fe19" integrity sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA== @@ -1835,6 +2104,11 @@ punycode.js@^2.3.1: resolved "https://registry.yarnpkg.com/punycode.js/-/punycode.js-2.3.1.tgz#6b53e56ad75588234e79f4affa90972c7dd8cdb7" integrity sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA== +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -1871,6 +2145,42 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +remark-parse@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-9.0.0.tgz#4d20a299665880e4f4af5d90b7c7b8a935853640" + integrity sha512-geKatMwSzEXKHuzBNU1z676sGcDcFoChMK38TgdHJNAYfFtsfHDQG7MoJAjs6sgYMqyLduCYWDIWZIxiPeafEw== + dependencies: + mdast-util-from-markdown "^0.8.0" + +remark-stringify@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-9.0.1.tgz#576d06e910548b0a7191a71f27b33f1218862894" + integrity sha512-mWmNg3ZtESvZS8fv5PTvaPckdL4iNlCHTt8/e/8oN08nArHRHjNZMKzA/YW3+p7/lYqIw4nx1XsjCBo/AxNChg== + dependencies: + mdast-util-to-markdown "^0.6.0" + +remark@^13.0.0: + version "13.0.0" + resolved "https://registry.yarnpkg.com/remark/-/remark-13.0.0.tgz#d15d9bf71a402f40287ebe36067b66d54868e425" + integrity sha512-HDz1+IKGtOyWN+QgBiAT0kn+2s6ovOxHyPAFGKVE81VSzJ+mq7RwHFledEvB5F1p4iJvOah/LOKdFuzvRnNLCA== + dependencies: + remark-parse "^9.0.0" + remark-stringify "^9.0.0" + unified "^9.1.0" + +repeat-string@^1.0.0: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== + +require@^2.4.20: + version "2.4.20" + resolved "https://registry.yarnpkg.com/require/-/require-2.4.20.tgz#66cb6baaabb65de8a71d793f5c65fd184f3798b6" + integrity sha512-7eop5rvh38qhQQQOoUyf68meVIcxT2yFySNywTbxoEECgkX4KDqqDRaEszfvFnuB3fuZVjDdJZ1TI/Esr16RRA== + dependencies: + std "0.1.40" + uglify-js "2.3.0" + resolve@^1.1.7, resolve@^1.22.8: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" @@ -1924,6 +2234,20 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +schema-utils@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" + integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +semver@^7.3.5: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -1976,6 +2300,18 @@ source-map-js@^1.2.0, source-map-js@^1.2.1: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== +source-map@~0.1.7: + version "0.1.43" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" + integrity sha512-VtCvB9SIQhk3aF6h+N85EaqIaBFIAfZ9Cu+NJHHVvc8BbEcnvDcFw6sqQ2dQrT6SlOrZq3tIvyD9+EGq/lJryQ== + dependencies: + amdefine ">=0.0.4" + +std@0.1.40: + version "0.1.40" + resolved "https://registry.yarnpkg.com/std/-/std-0.1.40.tgz#3678a5f65094d9e1b6b5e26edbfc0212b8342b71" + integrity sha512-wUf57hkDGCoVShrhPA8Q7lAg2Qosk+FaMlECmAsr1A4/rL2NRXFHQGBcgMUFKVkPEemJFW9gzjCQisRty14ohg== + "string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -2024,6 +2360,14 @@ strip-ansi@^7.0.1: dependencies: ansi-regex "^6.0.1" +style-loader@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-2.0.0.tgz#9669602fd4690740eaaec137799a03addbbc393c" + integrity sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ== + dependencies: + loader-utils "^2.0.0" + schema-utils "^3.0.0" + sucrase@^3.35.0: version "3.35.0" resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.35.0.tgz#57f17a3d7e19b36d8995f06679d121be914ae263" @@ -2098,6 +2442,11 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +trough@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" + integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== + ts-interface-checker@^0.1.9: version "0.1.13" resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" @@ -2118,6 +2467,34 @@ uc.micro@^2.0.0, uc.micro@^2.1.0: resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-2.1.0.tgz#f8d3f7d0ec4c3dea35a7e3c8efa4cb8b45c9e7ee" integrity sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A== +uglify-js@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.3.0.tgz#2cdec16d378a8a2b6ecfb6989784cf8b7ae5491f" + integrity sha512-AQvbxRKdaQeYADywQaao0k8Tj+7NGEVTne6xwgX1yQpv/G8b0CKdIw70HkCptwfvNGDsVe+0Bng3U9hfWbxxfg== + dependencies: + async "~0.2.6" + optimist "~0.3.5" + source-map "~0.1.7" + +unified@^9.1.0: + version "9.2.2" + resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.2.tgz#67649a1abfc3ab85d2969502902775eb03146975" + integrity sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ== + dependencies: + bail "^1.0.0" + extend "^3.0.0" + is-buffer "^2.0.0" + is-plain-obj "^2.0.0" + trough "^1.0.0" + vfile "^4.0.0" + +unist-util-stringify-position@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da" + integrity sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g== + dependencies: + "@types/unist" "^2.0.2" + update-browserslist-db@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz#80846fba1d79e82547fb661f8d141e0945755fe5" @@ -2126,11 +2503,36 @@ update-browserslist-db@^1.1.1: escalade "^3.2.0" picocolors "^1.1.0" +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + util-deprecate@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== +vfile-message@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.4.tgz#5b43b88171d409eae58477d13f23dd41d52c371a" + integrity sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ== + dependencies: + "@types/unist" "^2.0.0" + unist-util-stringify-position "^2.0.0" + +vfile@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.2.1.tgz#03f1dce28fc625c625bc6514350fbdb00fa9e624" + integrity sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA== + dependencies: + "@types/unist" "^2.0.0" + is-buffer "^2.0.0" + unist-util-stringify-position "^2.0.0" + vfile-message "^2.0.0" + vite@^5.0.11: version "5.4.11" resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.11.tgz#3b415cd4aed781a356c1de5a9ebafb837715f6e5" @@ -2194,6 +2596,11 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + integrity sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw== + "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -2226,3 +2633,8 @@ yaml@^2.3.4: version "2.6.1" resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.6.1.tgz#42f2b1ba89203f374609572d5349fb8686500773" integrity sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg== + +zwitch@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920" + integrity sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw== From 802d4ccb0b8007e0f4317b6da608aba342e7e7ae Mon Sep 17 00:00:00 2001 From: frappe-pr-bot Date: Fri, 13 Dec 2024 16:04:40 +0000 Subject: [PATCH 02/16] chore: update POT file --- lms/locale/main.pot | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/lms/locale/main.pot b/lms/locale/main.pot index 343942c0..d1b8bc80 100644 --- a/lms/locale/main.pot +++ b/lms/locale/main.pot @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: Frappe LMS VERSION\n" "Report-Msgid-Bugs-To: jannat@frappe.io\n" -"POT-Creation-Date: 2024-12-06 16:04+0000\n" -"PO-Revision-Date: 2024-12-06 16:04+0000\n" +"POT-Creation-Date: 2024-12-13 16:04+0000\n" +"PO-Revision-Date: 2024-12-13 16:04+0000\n" "Last-Translator: jannat@frappe.io\n" "Language-Team: jannat@frappe.io\n" "MIME-Version: 1.0\n" @@ -99,7 +99,7 @@ msgstr "" #: frontend/src/components/Assessments.vue:11 #: frontend/src/components/BatchCourses.vue:11 -#: frontend/src/components/BatchStudents.vue:6 +#: frontend/src/components/BatchStudents.vue:10 #: frontend/src/components/Categories.vue:26 #: frontend/src/components/LiveClass.vue:11 #: frontend/src/components/Members.vue:43 frontend/src/pages/ProgramForm.vue:30 @@ -1700,7 +1700,7 @@ msgstr "" msgid "Enrollment Count" msgstr "" -#: lms/lms/utils.py:1702 +#: lms/lms/utils.py:1715 msgid "Enrollment Failed" msgstr "" @@ -1736,6 +1736,7 @@ msgstr "" #: frontend/src/components/Modals/Question.vue:249 #: frontend/src/components/Modals/Question.vue:269 #: frontend/src/components/Modals/Question.vue:326 +#: frontend/src/components/Modals/StudentModal.vue:69 #: frontend/src/components/SettingDetails.vue:62 #: frontend/src/pages/Billing.vue:264 frontend/src/pages/QuizForm.vue:350 #: frontend/src/pages/QuizForm.vue:365 @@ -2810,7 +2811,7 @@ msgstr "" msgid "LiveCode URL" msgstr "" -#: frontend/src/components/Members.vue:95 +#: frontend/src/components/Members.vue:106 msgid "Load More" msgstr "" @@ -3228,7 +3229,7 @@ msgstr "" msgid "Next Question" msgstr "" -#: frontend/src/components/Assessments.vue:63 lms/templates/assessments.html:58 +#: frontend/src/components/Assessments.vue:66 lms/templates/assessments.html:58 msgid "No Assessments" msgstr "" @@ -3685,7 +3686,7 @@ msgstr "" msgid "Please click on the following button to set your new password" msgstr "" -#: lms/lms/utils.py:1824 lms/lms/utils.py:1828 +#: lms/lms/utils.py:1837 lms/lms/utils.py:1841 msgid "Please complete the previous courses in the program to enroll in this course." msgstr "" @@ -4698,13 +4699,13 @@ msgstr "" #. Label of the students (Table) field in DocType 'LMS Batch' #. Label of the show_students (Check) field in DocType 'LMS Settings' -#: frontend/src/components/BatchStudents.vue:9 +#: frontend/src/components/BatchStudents.vue:4 #: lms/lms/doctype/lms_batch/lms_batch.json #: lms/lms/doctype/lms_settings/lms_settings.json msgid "Students" msgstr "" -#: frontend/src/components/BatchStudents.vue:157 +#: frontend/src/components/BatchStudents.vue:191 msgid "Students deleted successfully" msgstr "" @@ -4756,7 +4757,7 @@ msgstr "" #: frontend/src/components/BatchCourses.vue:150 #: frontend/src/components/BatchOverlay.vue:135 -#: frontend/src/components/BatchStudents.vue:157 +#: frontend/src/components/BatchStudents.vue:191 #: frontend/src/components/CourseCardOverlay.vue:161 #: frontend/src/components/Modals/AnnouncementModal.vue:99 #: frontend/src/components/Modals/AssessmentModal.vue:73 @@ -4944,7 +4945,7 @@ msgstr "" msgid "There are no seats available in this batch." msgstr "" -#: frontend/src/components/BatchStudents.vue:67 +#: frontend/src/components/BatchStudents.vue:86 msgid "There are no students in this batch." msgstr "" @@ -4975,7 +4976,7 @@ msgstr "" msgid "This course has:" msgstr "" -#: lms/lms/utils.py:1582 +#: lms/lms/utils.py:1595 msgid "This course is free." msgstr "" @@ -5117,7 +5118,7 @@ msgstr "" msgid "To Date" msgstr "" -#: lms/lms/utils.py:1593 +#: lms/lms/utils.py:1606 msgid "To join this batch, please contact the Administrator." msgstr "" From 7f44177986904989e76e945726b8a4b16f264469 Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Mon, 16 Dec 2024 16:41:55 +0530 Subject: [PATCH 03/16] feat: markdown parser for links and lists --- README.md | 6 +- frontend/src/components/CourseCard.vue | 2 +- .../components/Modals/ExplanationVideos.vue | 2 +- frontend/src/pages/LessonForm.vue | 1 + frontend/src/utils/index.js | 11 +- frontend/src/utils/markdownParser.js | 228 +++++++++--------- 6 files changed, 131 insertions(+), 119 deletions(-) diff --git a/README.md b/README.md index be054c58..6b06f476 100644 --- a/README.md +++ b/README.md @@ -23,10 +23,10 @@ ## Frappe Learning Frappe Learning is an easy-to-use learning system that helps you bring structure to your content. -## Motivation +### Motivation In 2021, we were looking for a Learning Management System to launch [Mon.School](https://mon.school) for FOSS United. We checked out Moodle, but it didn’t feel right. The forms were unnecessarily lengthy and the UI was confusing. It shouldn't be this hard to create a course right? So I started making a learning system for Mon.School which soon became a product in itself. The aim is to have a simple platform that anyone can use to launch a course of their own and make knowledge sharing easier. -## Key Features +### Key Features - **Structured Learning**: Design a course with a 3-level hierarchy, where your courses have chapters and you can group your lessons within these chapters. This ensures that the context of the lesson is set by the chapter. @@ -67,7 +67,7 @@ In 2021, we were looking for a Learning Management System to launch [Mon.School] -## Under the Hood +### Under the Hood - [**Frappe Framework**](https://github.com/frappe/frappe): A full-stack web application framework. diff --git a/frontend/src/components/CourseCard.vue b/frontend/src/components/CourseCard.vue index 50673e82..790153c4 100644 --- a/frontend/src/components/CourseCard.vue +++ b/frontend/src/components/CourseCard.vue @@ -59,7 +59,7 @@
diff --git a/frontend/src/components/Modals/ExplanationVideos.vue b/frontend/src/components/Modals/ExplanationVideos.vue index b6e7ceef..2f362cb4 100644 --- a/frontend/src/components/Modals/ExplanationVideos.vue +++ b/frontend/src/components/Modals/ExplanationVideos.vue @@ -26,7 +26,7 @@ const props = defineProps({ required: true, }, title: { - type: String, + type: [String, null], required: true, }, }) diff --git a/frontend/src/pages/LessonForm.vue b/frontend/src/pages/LessonForm.vue index ed83bf04..ee1aee23 100644 --- a/frontend/src/pages/LessonForm.vue +++ b/frontend/src/pages/LessonForm.vue @@ -132,6 +132,7 @@ const renderEditor = (holder) => { holder: holder, tools: getEditorTools(true), autofocus: true, + defaultBlock: 'markdownParser', }) } diff --git a/frontend/src/utils/index.js b/frontend/src/utils/index.js index d0d9e8a7..789005dc 100644 --- a/frontend/src/utils/index.js +++ b/frontend/src/utils/index.js @@ -13,8 +13,6 @@ import dayjs from '@/utils/dayjs' import Embed from '@editorjs/embed' import SimpleImage from '@editorjs/simple-image' import Table from '@editorjs/table' -import MDParser from 'editorjs-md-parser' -import MDImporter from 'editorjs-md-parser' export function createToast(options) { toast({ @@ -150,7 +148,12 @@ export function htmlToText(html) { export function getEditorTools() { return { - header: Header, + header: { + class: Header, + config: { + placeholder: 'Header', + }, + }, quiz: Quiz, upload: Upload, markdownParser: MarkdownParser, @@ -184,7 +187,7 @@ export function getEditorTools() { }, embed: { class: Embed, - inlineToolbar: false, + inlineToolbar: true, config: { services: { youtube: { diff --git a/frontend/src/utils/markdownParser.js b/frontend/src/utils/markdownParser.js index 2d8dbcb9..64b383bc 100644 --- a/frontend/src/utils/markdownParser.js +++ b/frontend/src/utils/markdownParser.js @@ -1,143 +1,151 @@ export class MarkdownParser { constructor({ data, api, readOnly, config }) { - console.log('markdownParser constructor called') this.api = api this.data = data || {} this.config = config || {} - this.text = this.data.text || '' + this.text = data.text || '' this.readOnly = readOnly } - static get toolbox() { - const app = createApp({ - render: () => - h(UploadIcon, { size: 18, strokeWidth: 1.5, color: 'black' }), - }) - - const div = document.createElement('div') - app.mount(div) - - return { - title: 'Upload', - icon: div.innerHTML, - } - } - static get isReadOnlySupported() { return true } + static get conversionConfig() { + return { + export: 'text', + import: 'text', + } + } + render() { - console.log(' render() called') - const container = document.createElement('div') - container.contentEditable = true // Make the div editable like a textarea - container.classList.add('markdown-parser') - container.textContent = this.text + this.wrapper = document.createElement('div') + this.wrapper.classList.add('cdx-block') + this.wrapper.classList.add('ce-paragraph') + this.wrapper.innerHTML = this.text - container.addEventListener('blur', () => { - this.text = container.textContent.trim() - this.parseMarkdown() - }) + if (!this.readOnly) { + this.wrapper.contentEditable = true + this.wrapper.innerHTML = this.text - this.textArea = container - return container + this.wrapper.addEventListener('keydown', (event) => { + const value = event.target.textContent + if (event.keyCode === 32 && value.startsWith('#')) { + this.convertToHeader(event, value) + } else if (event.keyCode === 13) { + this.parseContent(event) + } + }) + + this.wrapper.addEventListener('paste', (event) => + this.handlePaste(event) + ) + } + + return this.wrapper + } + + convertToHeader(event, value) { + event.preventDefault() + if (['#', '##', '###', '####', '#####', '######'].includes(value)) { + let level = value.length + event.target.textContent = '' + this.convertBlock('header', { + level: level, + }) + } + } + + parseContent(event) { + event.preventDefault() + const previousLine = this.wrapper.textContent + if (previousLine && this.hasImage(previousLine)) { + this.wrapper.textContent = '' + this.convertBlock('image') + } else if (previousLine && this.hasLink(previousLine)) { + const { text, url } = this.extractLink(previousLine) + const anchorTag = `${text}` + this.convertBlock('paragraph', { + text: previousLine.replace(/\[.+?\]\(.+?\)/, anchorTag), + }) + } else if (previousLine && previousLine.startsWith('- ')) { + this.convertBlock('list', { + style: 'unordered', + items: [ + { + content: previousLine.replace('- ', ''), + }, + ], + }) + } else if (previousLine && previousLine.startsWith('1. ')) { + this.convertBlock('list', { + style: 'ordered', + items: [ + { + content: previousLine.replace('1. ', ''), + }, + ], + }) + } else if (previousLine && this.canBeEmbed(previousLine)) { + this.wrapper.textContent = '' + this.convertBlock('embed', { + source: previousLine, + }) + } + } + + async convertBlock(type, data, index = null) { + const currentIndex = this.api.blocks.getCurrentBlockIndex() + const currentBlock = this.api.blocks.getBlockByIndex(currentIndex) + await this.api.blocks.convert(currentBlock.id, type, data) + this.api.caret.focus(true) + } + + handlePaste(event) { + event.preventDefault() + + const clipboardData = event.clipboardData || window.clipboardData + const pastedText = clipboardData.getData('text/plain') + const sanitizedText = this.processPastedContent(pastedText) + document.execCommand('insertText', false, sanitizedText) + } + + processPastedContent(text) { + return text.trim() } save(blockContent) { return { - text: this.text, + text: blockContent.innerHTML, } } - /** - * Parse Markdown text and render Editor.js blocks. - */ - parseMarkdown() { - console.log(' parseMarkdown() called') - const markdown = this.text - const lines = markdown.split('\n') - - const blocks = lines.map((line) => { - if (line.startsWith('# ')) { - return { - type: 'header', - data: { text: line.replace('# ', ''), level: 1 }, - } - } else if (line.startsWith('## ')) { - return { - type: 'header', - data: { text: line.replace('## ', ''), level: 2 }, - } - } else if (line.startsWith('- ')) { - return { - type: 'list', - data: { - items: [line.replace('- ', '')], - style: 'unordered', - }, - } - } else if (this.isImage(line)) { - const { alt, url } = this.extractImage(line) - return { - type: 'image', - data: { - file: { url }, - caption: alt, - withBorder: false, - stretched: false, - withBackground: false, - }, - } - } else if (this.isLink(line)) { - const { text, url } = this.extractLink(line) - return { - type: 'linkTool', - data: { link: url, meta: { title: text } }, - } - } else { - return { type: 'paragraph', data: { text: line } } - } - }) - - this.api.blocks.render({ blocks }) + hasImage(line) { + return /!\[.+?\]\(.+?\)/.test(line) } - /** - * Check if the line matches the image syntax. - * @param {string} line - The line of text. - * @returns {boolean} - */ - isImage(line) { - return /^!\[.*\]\(.*\)$/.test(line) - } - - /** - * Extract alt text and URL from the image syntax. - * @param {string} line - The line of text. - * @returns {Object} { alt, url } - */ extractImage(line) { - const match = line.match(/^!\[(.*)\]\((.*)\)$/) - return { alt: match[1], url: match[2] } + const match = line.match(/!\[(.+?)\]\((.+?)\)/) + if (match) { + return { alt: match[1], url: match[2] } + } + return { alt: '', url: '' } } - /** - * Check if the line matches the link syntax. - * @param {string} line - The line of text. - * @returns {boolean} - */ - isLink(line) { - return /^\[.*\]\(.*\)$/.test(line) + hasLink(line) { + return /\[.+?\]\(.+?\)/.test(line) } - /** - * Extract text and URL from the link syntax. - * @param {string} line - The line of text. - * @returns {Object} { text, url } - */ extractLink(line) { - const match = line.match(/^\[(.*)\]\((.*)\)$/) - return { text: match[1], url: match[2] } + const match = line.match(/\[(.+?)\]\((.+?)\)/) + if (match) { + return { text: match[1], url: match[2] } + } + return { text: '', url: '' } + } + + canBeEmbed(line) { + return /^https?:\/\/.+/.test(line) } } From ae8008d05cbb8083568ee2c02c656716713fb4b1 Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Mon, 16 Dec 2024 17:00:55 +0530 Subject: [PATCH 04/16] chore: bumped up mariadb image version --- .github/helper/install_dependencies.sh | 2 +- .github/workflows/ui-tests.yml | 2 +- docker/docker-compose.yml | 2 +- frontend/package.json | 1 - frontend/src/utils/index.js | 2 +- 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/helper/install_dependencies.sh b/.github/helper/install_dependencies.sh index 574144b8..8f5d06cd 100644 --- a/.github/helper/install_dependencies.sh +++ b/.github/helper/install_dependencies.sh @@ -5,7 +5,7 @@ echo "Setting Up System Dependencies..." sudo apt update sudo apt remove mysql-server mysql-client -sudo apt install libcups2-dev redis-server mariadb-client-10.6 +sudo apt install libcups2-dev redis-server mariadb-client-10.8 install_wkhtmltopdf() { wget -q https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb diff --git a/.github/workflows/ui-tests.yml b/.github/workflows/ui-tests.yml index f093e55a..e5d9171b 100644 --- a/.github/workflows/ui-tests.yml +++ b/.github/workflows/ui-tests.yml @@ -24,7 +24,7 @@ jobs: services: mariadb: - image: mariadb:10.6 + image: mariadb:10.8 env: MARIADB_ROOT_PASSWORD: 123 ports: diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index a01fdb84..5473e7b2 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -2,7 +2,7 @@ version: "3.7" name: lms services: mariadb: - image: mariadb:10.6 + image: mariadb:10.8 command: - --character-set-server=utf8mb4 - --collation-server=utf8mb4_unicode_ci diff --git a/frontend/package.json b/frontend/package.json index 44cbca2a..0fc71fa3 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -23,7 +23,6 @@ "chart.js": "^4.4.1", "codemirror-editor-vue3": "^2.8.0", "dayjs": "^1.11.6", - "editorjs-md-parser": "^0.0.3", "feather-icons": "^4.28.0", "frappe-ui": "^0.1.89", "lucide-vue-next": "^0.383.0", diff --git a/frontend/src/utils/index.js b/frontend/src/utils/index.js index 789005dc..ac144b8f 100644 --- a/frontend/src/utils/index.js +++ b/frontend/src/utils/index.js @@ -161,7 +161,7 @@ export function getEditorTools() { table: Table, paragraph: { class: Paragraph, - inlineToolbar: true, + inlineToolbar: false, config: { preserveBlank: true, }, From 51a6cc035cd5ddec1ca8d23603b5293857b088ea Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Mon, 16 Dec 2024 17:14:30 +0530 Subject: [PATCH 05/16] fix: delete quiz and submission before deleting course --- lms/lms/api.py | 5 +++-- lms/lms/doctype/lms_quiz_submission/lms_quiz_submission.py | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lms/lms/api.py b/lms/lms/api.py index 908a1dc0..e6430277 100644 --- a/lms/lms/api.py +++ b/lms/lms/api.py @@ -841,8 +841,6 @@ def delete_course(course): frappe.delete_doc("Lesson Reference", lesson) for lesson in lessons: - frappe.db.delete("LMS Course Progress", {"lesson": lesson}) - topics = frappe.get_all( "Discussion Topic", {"reference_doctype": "Course Lesson", "reference_docname": lesson}, @@ -862,6 +860,9 @@ def delete_course(course): for chapter in chapters: frappe.delete_doc("Course Chapter", chapter) + frappe.db.delete("LMS Course Progress", {"course": course}) + frappe.db.delete("LMS Quiz", {"course": course}) + frappe.db.delete("LMS Quiz Submission", {"course": course}) frappe.db.delete("LMS Enrollment", {"course": course}) frappe.delete_doc("LMS Course", course) diff --git a/lms/lms/doctype/lms_quiz_submission/lms_quiz_submission.py b/lms/lms/doctype/lms_quiz_submission/lms_quiz_submission.py index 0998c3f6..0618eb2b 100644 --- a/lms/lms/doctype/lms_quiz_submission/lms_quiz_submission.py +++ b/lms/lms/doctype/lms_quiz_submission/lms_quiz_submission.py @@ -17,6 +17,7 @@ class LMSQuizSubmission(Document): self.notify_member() def validate_marks(self): + self.score = 0 for row in self.result: if cint(row.marks) > cint(row.marks_out_of): frappe.throw( From 75c11d3fcc6353aa94875bce27199443717047eb Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Mon, 16 Dec 2024 17:21:12 +0530 Subject: [PATCH 06/16] fix: course category was not reflecting on course form --- frontend/src/pages/CourseForm.vue | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend/src/pages/CourseForm.vue b/frontend/src/pages/CourseForm.vue index b4de038f..79b58638 100644 --- a/frontend/src/pages/CourseForm.vue +++ b/frontend/src/pages/CourseForm.vue @@ -133,8 +133,8 @@
@@ -288,6 +288,7 @@ const course = reactive({ video_link: '', course_image: null, tags: '', + category: '', published: false, published_on: '', featured: false, From a81b384f90c6bb956905b53421ff6a1600d29b65 Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Mon, 16 Dec 2024 17:30:00 +0530 Subject: [PATCH 07/16] fix: mariadb dependency installation --- .github/helper/install_dependencies.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/helper/install_dependencies.sh b/.github/helper/install_dependencies.sh index 574144b8..d5a3929f 100644 --- a/.github/helper/install_dependencies.sh +++ b/.github/helper/install_dependencies.sh @@ -5,7 +5,7 @@ echo "Setting Up System Dependencies..." sudo apt update sudo apt remove mysql-server mysql-client -sudo apt install libcups2-dev redis-server mariadb-client-10.6 +sudo apt-get install libcups2-dev redis-server mariadb-client-10.6 install_wkhtmltopdf() { wget -q https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb From 3288fb0f065a330cd971c19c698f88f1162f5716 Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Mon, 16 Dec 2024 17:56:57 +0530 Subject: [PATCH 08/16] chore: replace mariadb-client-10.6 with mariadb-client for ui tests --- .github/helper/install_dependencies.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/helper/install_dependencies.sh b/.github/helper/install_dependencies.sh index d5a3929f..beb0cd34 100644 --- a/.github/helper/install_dependencies.sh +++ b/.github/helper/install_dependencies.sh @@ -5,7 +5,7 @@ echo "Setting Up System Dependencies..." sudo apt update sudo apt remove mysql-server mysql-client -sudo apt-get install libcups2-dev redis-server mariadb-client-10.6 +sudo apt-get install libcups2-dev redis-server mariadb-client install_wkhtmltopdf() { wget -q https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb From 86e7e68ce1933598e1d182c6bb666bb8c5eb44fc Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Mon, 16 Dec 2024 18:12:13 +0530 Subject: [PATCH 09/16] chore: removed unused packages --- frontend/package.json | 1 - frontend/src/utils/index.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index 44cbca2a..0fc71fa3 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -23,7 +23,6 @@ "chart.js": "^4.4.1", "codemirror-editor-vue3": "^2.8.0", "dayjs": "^1.11.6", - "editorjs-md-parser": "^0.0.3", "feather-icons": "^4.28.0", "frappe-ui": "^0.1.89", "lucide-vue-next": "^0.383.0", diff --git a/frontend/src/utils/index.js b/frontend/src/utils/index.js index 789005dc..ac144b8f 100644 --- a/frontend/src/utils/index.js +++ b/frontend/src/utils/index.js @@ -161,7 +161,7 @@ export function getEditorTools() { table: Table, paragraph: { class: Paragraph, - inlineToolbar: true, + inlineToolbar: false, config: { preserveBlank: true, }, From e0169cff7998428d07dc01c127db09d732561ec6 Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Mon, 16 Dec 2024 19:12:15 +0530 Subject: [PATCH 10/16] fix: scormcontent package load issue --- lms/page_renderers.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lms/page_renderers.py b/lms/page_renderers.py index 68daa5b6..91daf29d 100644 --- a/lms/page_renderers.py +++ b/lms/page_renderers.py @@ -162,3 +162,14 @@ class SCORMRenderer(BaseRenderer): ) response.mimetype = mimetypes.guess_type(path)[0] return response + else: + path = path.replace(".html", "") + if os.path.exists(path) and os.path.isdir(path): + index_path = os.path.join(path, "index.html") + if os.path.exists(index_path): + f = open(index_path, "rb") + response = Response( + wrap_file(frappe.local.request.environ, f), direct_passthrough=True + ) + response.mimetype = mimetypes.guess_type(index_path)[0] + return response From be930ce0762e3dd83efeb7f3e1d485809c0bb2b8 Mon Sep 17 00:00:00 2001 From: Jannat Patel <31363128+pateljannat@users.noreply.github.com> Date: Tue, 17 Dec 2024 05:37:38 +0530 Subject: [PATCH 11/16] chore: Persian translations --- lms/locale/fa.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lms/locale/fa.po b/lms/locale/fa.po index 38542cfd..4a8a271c 100644 --- a/lms/locale/fa.po +++ b/lms/locale/fa.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: frappe\n" "Report-Msgid-Bugs-To: jannat@frappe.io\n" "POT-Creation-Date: 2024-12-06 16:04+0000\n" -"PO-Revision-Date: 2024-12-09 23:31\n" +"PO-Revision-Date: 2024-12-17 00:07\n" "Last-Translator: jannat@frappe.io\n" "Language-Team: Persian\n" "MIME-Version: 1.0\n" @@ -2469,7 +2469,7 @@ msgstr "" #: frontend/src/pages/CourseForm.vue:136 msgid "Keywords for the course" -msgstr "" +msgstr "کلمات کلیدی برای دوره" #. Name of a Workspace #: lms/lms/workspace/lms/lms.json @@ -3265,7 +3265,7 @@ msgstr "" #: frontend/src/pages/Courses.vue:147 msgid "No courses found" -msgstr "" +msgstr "هیچ دوره ای پیدا نشد" #: frontend/src/pages/Programs.vue:83 msgid "No courses in this program" From 65dc2838d3af3dfb543eace558cb9bbf7de0e943 Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Tue, 17 Dec 2024 12:23:44 +0530 Subject: [PATCH 12/16] feat: load more in quiz submissions --- frontend/src/components/BatchStudents.vue | 31 ++++++++++++----------- frontend/src/pages/QuizSubmissionList.vue | 16 +++++++----- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/frontend/src/components/BatchStudents.vue b/frontend/src/components/BatchStudents.vue index 3d898d21..8717306b 100644 --- a/frontend/src/components/BatchStudents.vue +++ b/frontend/src/components/BatchStudents.vue @@ -52,7 +52,7 @@ {{ row[column.key] }}
- {{ Math.ceil(row.courses[column.key]) }}% + {{ Math.ceil(row.courses[column.key]) }}
{{ row.assessments[column.key] }} -
{{ parseInt(row.assessments[column.key]) }}%
+
{{ parseInt(row.assessments[column.key]) }}
@@ -134,22 +134,10 @@ const getStudentColumns = () => { { label: 'Full Name', key: 'full_name', - width: '10rem', + width: '15rem', }, ] - if (students.data?.[0].courses) { - Object.keys(students.data?.[0].courses).forEach((course) => { - columns.push({ - label: course, - key: course, - width: '10rem', - icon: 'book-open', - align: 'center', - }) - }) - } - if (students.data?.[0].assessments) { Object.keys(students.data?.[0].assessments).forEach((assessment) => { columns.push({ @@ -163,6 +151,19 @@ const getStudentColumns = () => { }) }) } + + if (students.data?.[0].courses) { + Object.keys(students.data?.[0].courses).forEach((course) => { + columns.push({ + label: course, + key: course, + width: '10rem', + icon: 'book-open', + align: 'center', + }) + }) + } + return columns } diff --git a/frontend/src/pages/QuizSubmissionList.vue b/frontend/src/pages/QuizSubmissionList.vue index 6aeea286..e9a06fdb 100644 --- a/frontend/src/pages/QuizSubmissionList.vue +++ b/frontend/src/pages/QuizSubmissionList.vue @@ -5,6 +5,9 @@
+
+ {{ submissions.data[0].quiz_title }} +
+
+ +