Browse Source

Merge remote-tracking branch 'origin/master' into feat/zip-import

mizozobu 6 years ago
parent
commit
f130540400

+ 11 - 2
CHANGES.md

@@ -1,8 +1,17 @@
 # CHANGES
 
-## 3.5.13-RC
+## 3.5.14-RC
 
-* 
+* Support: Upgrade libs
+    * codemirror
+
+## 3.5.13
+
+* Feature: Re-edit comments
+* Support: [growi-plugin-attachment-refs](https://github.com/weseek/growi-plugin-attachment-refs)
+* Support: Upgrade libs
+    * entities
+    * markdown-it
 
 ## 3.5.12
 

+ 1 - 0
config/env.dev.js

@@ -9,6 +9,7 @@ module.exports = {
   PLUGIN_NAMES_TOBE_LOADED: [
     // 'growi-plugin-lsx',
     // 'growi-plugin-pukiwiki-like-linker',
+    // 'growi-plugin-attachment-refs',
   ],
   // PUBLISH_OPEN_API: true,
   // USER_UPPER_LIMIT: 0,

+ 2 - 0
config/jest.config.js

@@ -6,6 +6,8 @@ module.exports = {
   verbose: true,
 
   rootDir: '../',
+  globalSetup: '<rootDir>/src/test/global-setup.js',
+  globalTeardown: '<rootDir>/src/test/global-teardown.js',
 
   projects: [
     {

+ 4 - 5
package.json

@@ -1,6 +1,6 @@
 {
   "name": "growi",
-  "version": "3.5.13-RC",
+  "version": "3.5.14-RC",
   "description": "Team collaboration software using markdown",
   "tags": [
     "wiki",
@@ -62,7 +62,6 @@
   "dependencies": {
     "//": [
       "check-node-version: see https://github.com/parshap/check-node-version/issues/35",
-      "entities: markdown-it@9.0.1 depends on entities@~1.1.1",
       "mongoose: somehow GlobalNotificationSetting CRUD does not work with mongoose v5.6.0",
       "openid-client: Node.js 12 or higher is required for openid-client@3 and above."
     ],
@@ -84,7 +83,7 @@
     "date-fns": "^2.0.0",
     "diff": "^4.0.1",
     "elasticsearch": "^16.0.0",
-    "entities": "=1.1.2",
+    "entities": "^2.0.0",
     "env-cmd": "^10.0.1",
     "esa-nodejs": "^0.0.7",
     "escape-string-regexp": "^2.0.0",
@@ -157,7 +156,7 @@
     "browser-sync": "^2.26.3",
     "bunyan-debug": "^2.0.0",
     "cli": "~1.0.1",
-    "codemirror": "^5.42.0",
+    "codemirror": "^5.48.4",
     "colors": "^1.2.5",
     "connect-browser-sync": "^2.1.0",
     "core-js": "=2.6.9",
@@ -181,7 +180,7 @@
     "jquery.cookie": "~1.4.1",
     "load-css-file": "^1.0.0",
     "lodash-webpack-plugin": "^0.11.5",
-    "markdown-it": "^9.0.1",
+    "markdown-it": "^10.0.0",
     "markdown-it-blockdiag": "^1.0.2",
     "markdown-it-emoji": "^1.4.0",
     "markdown-it-footnote": "^3.0.1",

+ 13 - 13
resource/cdn-manifests.js

@@ -46,28 +46,28 @@ module.exports = {
     },
     {
       name: 'codemirror-dialog',
-      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.42.0/addon/dialog/dialog.min.js',
+      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.48.4/addon/dialog/dialog.min.js',
       args: {
         integrity: '',
       },
     },
     {
       name: 'codemirror-keymap-vim',
-      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.42.0/keymap/vim.min.js',
+      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.48.4/keymap/vim.min.js',
       args: {
         integrity: '',
       },
     },
     {
       name: 'codemirror-keymap-emacs',
-      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.42.0/keymap/emacs.min.js',
+      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.48.4/keymap/emacs.min.js',
       args: {
         integrity: '',
       },
     },
     {
       name: 'codemirror-keymap-sublime',
-      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.42.0/keymap/sublime.min.js',
+      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.48.4/keymap/sublime.min.js',
       args: {
         integrity: '',
       },
@@ -145,63 +145,63 @@ module.exports = {
     },
     {
       name: 'codemirror-dialog',
-      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.42.0/addon/dialog/dialog.min.css',
+      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.48.4/addon/dialog/dialog.min.css',
       args: {
         integrity: '',
       },
     },
     {
       name: 'codemirror-theme-eclipse',
-      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.42.0/theme/eclipse.min.css',
+      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.48.4/theme/eclipse.min.css',
       args: {
         integrity: '',
       },
     },
     {
       name: 'codemirror-theme-elegant',
-      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.42.0/theme/elegant.min.css',
+      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.48.4/theme/elegant.min.css',
       args: {
         integrity: '',
       },
     },
     {
       name: 'codemirror-theme-neo',
-      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.42.0/theme/neo.min.css',
+      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.48.4/theme/neo.min.css',
       args: {
         integrity: '',
       },
     },
     {
       name: 'codemirror-theme-mdn-like',
-      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.42.0/theme/mdn-like.min.css',
+      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.48.4/theme/mdn-like.min.css',
       args: {
         integrity: '',
       },
     },
     {
       name: 'codemirror-theme-material',
-      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.42.0/theme/material.min.css',
+      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.48.4/theme/material.min.css',
       args: {
         integrity: '',
       },
     },
     {
       name: 'codemirror-theme-dracula',
-      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.42.0/theme/dracula.min.css',
+      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.48.4/theme/dracula.min.css',
       args: {
         integrity: '',
       },
     },
     {
       name: 'codemirror-theme-monokai',
-      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.42.0/theme/monokai.min.css',
+      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.48.4/theme/monokai.min.css',
       args: {
         integrity: '',
       },
     },
     {
       name: 'codemirror-theme-twilight',
-      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.42.0/theme/twilight.min.css',
+      url: 'https://cdn.jsdelivr.net/npm/codemirror@5.48.4/theme/twilight.min.css',
       args: {
         integrity: '',
       },

+ 14 - 0
src/client/js/components/PageComment/Comment.jsx

@@ -256,6 +256,8 @@ class Comment extends React.Component {
     const creator = comment.creator;
     const isMarkdown = comment.isMarkdown;
     const createdAt = new Date(comment.createdAt);
+    const updatedAt = new Date(comment.updatedAt);
+    const isEdited = createdAt < updatedAt;
 
     const showReEditor = this.state.showReEditorIds.has(commentId);
 
@@ -271,6 +273,13 @@ class Comment extends React.Component {
         {format(createdAt, 'yyyy/MM/dd HH:mm')}
       </Tooltip>
     );
+    const editedDateTooltip = isEdited
+      ? (
+        <Tooltip id={`editedDateTooltip-${comment._id}`}>
+          {format(updatedAt, 'yyyy/MM/dd HH:mm')}
+        </Tooltip>
+      )
+      : null;
 
     return (
       <React.Fragment>
@@ -295,6 +304,11 @@ class Comment extends React.Component {
                 <OverlayTrigger overlay={commentDateTooltip} placement="bottom">
                   <span>{commentDate}</span>
                 </OverlayTrigger>
+                { isEdited && (
+                  <OverlayTrigger overlay={editedDateTooltip} placement="bottom">
+                    <span>&nbsp;(edited)</span>
+                  </OverlayTrigger>
+                ) }
                 <span className="ml-2"><a className={revisionLavelClassName} href={revHref}>{revFirst8Letters}</a></span>
               </div>
               { this.checkPermissionToControlComment() && this.renderCommentControl(comment) }

+ 2 - 2
src/client/styles/bootstrap4/_mixins.scss

@@ -5,7 +5,7 @@
 // Utilities
 @import 'mixins/breakpoints';
 // @import "mixins/hover";
-// @import "mixins/image";
+@import 'mixins/image';
 // @import "mixins/badge";
 // @import "mixins/resize";
 // @import "mixins/screen-reader";
@@ -29,7 +29,7 @@
 
 // // Skins
 // @import "mixins/background-variant";
-// @import "mixins/border-radius";
+@import 'mixins/border-radius';
 // @import "mixins/box-shadow";
 // @import "mixins/gradients";
 // @import "mixins/transition";

+ 1 - 1
src/client/styles/bootstrap4/_utilities.scss

@@ -9,7 +9,7 @@
 @import 'utilities/position';
 // @import "utilities/screenreaders";
 // @import "utilities/shadows";
-// @import "utilities/sizing";
+@import 'utilities/sizing';
 @import 'utilities/spacing';
 @import 'utilities/text';
 // @import "utilities/visibility";

+ 49 - 49
src/client/styles/bootstrap4/_variables.scss

@@ -7,17 +7,17 @@
 // // Color system
 // //
 
-// $white:    #fff !default;
-// $gray-100: #f8f9fa !default;
-// $gray-200: #e9ecef !default;
-// $gray-300: #dee2e6 !default;
-// $gray-400: #ced4da !default;
-// $gray-500: #adb5bd !default;
-// $gray-600: #6c757d !default;
-// $gray-700: #495057 !default;
-// $gray-800: #343a40 !default;
-// $gray-900: #212529 !default;
-// $black:    #000 !default;
+$white:    #fff !default;
+$gray-100: #f8f9fa !default;
+$gray-200: #e9ecef !default;
+$gray-300: #dee2e6 !default;
+$gray-400: #ced4da !default;
+$gray-500: #adb5bd !default;
+$gray-600: #6c757d !default;
+$gray-700: #495057 !default;
+$gray-800: #343a40 !default;
+$gray-900: #212529 !default;
+$black:    #000 !default;
 
 // $grays: () !default;
 // // stylelint-disable-next-line scss/dollar-variable-default
@@ -103,18 +103,18 @@
 // $yiq-text-dark:             $gray-900 !default;
 // $yiq-text-light:            $white !default;
 
-// // Options
-// //
-// // Quickly modify global styling by enabling or disabling optional features.
+// Options
+//
+// Quickly modify global styling by enabling or disabling optional features.
 
-// $enable-caret:              true !default;
-// $enable-rounded:            true !default;
-// $enable-shadows:            false !default;
-// $enable-gradients:          false !default;
-// $enable-transitions:        true !default;
-// $enable-hover-media-query:  false !default; // Deprecated, no longer affects any compiled CSS
-// $enable-grid-classes:       true !default;
-// $enable-print-styles:       true !default;
+$enable-caret:              true !default;
+$enable-rounded:            true !default;
+$enable-shadows:            false !default;
+$enable-gradients:          false !default;
+$enable-transitions:        true !default;
+$enable-hover-media-query:  false !default; // Deprecated, no longer affects any compiled CSS
+$enable-grid-classes:       true !default;
+$enable-print-styles:       true !default;
 
 // Spacing
 //
@@ -145,19 +145,19 @@ $spacers: map-merge(
   $spacers
 );
 
-// // This variable affects the `.h-*` and `.w-*` classes.
-// $sizes: () !default;
-// // stylelint-disable-next-line scss/dollar-variable-default
-// $sizes: map-merge(
-//   (
-//     25: 25%,
-//     50: 50%,
-//     75: 75%,
-//     100: 100%,
-//     auto: auto
-//   ),
-//   $sizes
-// );
+// This variable affects the `.h-*` and `.w-*` classes.
+$sizes: () !default;
+// stylelint-disable-next-line scss/dollar-variable-default
+$sizes: map-merge(
+  (
+    25: 25%,
+    50: 50%,
+    75: 75%,
+    100: 100%,
+    auto: auto
+  ),
+  $sizes
+);
 
 // // Body
 // //
@@ -224,12 +224,12 @@ $grid-breakpoints: (
 // $line-height-lg:              1.5 !default;
 // $line-height-sm:              1.5 !default;
 
-// $border-width:                1px !default;
-// $border-color:                $gray-300 !default;
+$border-width:                1px !default;
+$border-color:                $gray-300 !default;
 
-// $border-radius:               .25rem !default;
-// $border-radius-lg:            .3rem !default;
-// $border-radius-sm:            .2rem !default;
+$border-radius:               .25rem !default;
+$border-radius-lg:            .3rem !default;
+$border-radius-sm:            .2rem !default;
 
 // $box-shadow-sm:               0 .125rem .25rem rgba($black, .075) !default;
 // $box-shadow:                  0 .5rem 1rem rgba($black, .15) !default;
@@ -859,17 +859,17 @@ $zindex-fixed:                      1030 !default;
 
 // // Image thumbnails
 
-// $thumbnail-padding:                 .25rem !default;
-// $thumbnail-bg:                      $body-bg !default;
-// $thumbnail-border-width:            $border-width !default;
-// $thumbnail-border-color:            $gray-300 !default;
-// $thumbnail-border-radius:           $border-radius !default;
-// $thumbnail-box-shadow:              0 1px 2px rgba($black, .075) !default;
+$thumbnail-padding:                 .25rem !default;
+$thumbnail-bg:                      $body-bg !default;
+$thumbnail-border-width:            $border-width !default;
+$thumbnail-border-color:            $gray-300 !default;
+$thumbnail-border-radius:           $border-radius !default;
+$thumbnail-box-shadow:              0 1px 2px rgba($black, .075) !default;
 
-// // Figures
+// Figures
 
-// $figure-caption-font-size:          90% !default;
-// $figure-caption-color:              $gray-600 !default;
+$figure-caption-font-size:          90% !default;
+$figure-caption-color:              $gray-600 !default;
 
 // // Breadcrumbs
 

+ 1 - 1
src/client/styles/bootstrap4/bootstrap.scss

@@ -11,7 +11,7 @@
 // @import "root";
 // @import "reboot";
 // @import "type";
-// @import "images";
+@import 'images';
 // @import "code";
 // @import "grid";
 // @import "tables";

+ 1 - 1
src/client/styles/scss/_layout.scss

@@ -64,7 +64,7 @@
     position: fixed;
     right: 25%;
     bottom: 25px;
-    z-index: 1039;
+    z-index: 1;
     display: block;
     padding: 5px 8px;
     font-size: 0.8em;

+ 1 - 1
src/client/styles/scss/_search.scss

@@ -210,7 +210,7 @@
 .search-page-input {
   position: sticky;
   top: 0;
-  z-index: 99;
+  z-index: 1;
 
   // for sticky layout
   padding-top: 15px;

+ 6 - 21
src/server/models/attachment.js

@@ -1,7 +1,6 @@
 // disable no-return-await for model functions
 /* eslint-disable no-return-await */
 
-const debug = require('debug')('growi:models:attachment');
 // eslint-disable-next-line no-unused-vars
 const logger = require('@alias/logger')('growi:models:attachment');
 const path = require('path');
@@ -68,28 +67,14 @@ module.exports = function(crowi) {
     return attachment;
   };
 
-  attachmentSchema.statics.removeAttachmentsByPageId = function(pageId) {
-    const Attachment = this;
+  attachmentSchema.statics.removeAttachmentsByPageId = async function(pageId) {
+    const attachments = await this.find({ page: pageId });
 
-    return new Promise((resolve, reject) => {
-      Attachment.find({ page: pageId })
-        .then((attachments) => {
-          for (const attachment of attachments) {
-            Attachment.removeWithSubstanceById(attachment._id)
-              .then((res) => {
-                // do nothing
-              })
-              .catch((err) => {
-                debug('Attachment remove error', err);
-              });
-          }
-
-          resolve(attachments);
-        })
-        .catch((err) => {
-          reject(err);
-        });
+    const promises = attachments.map(async(attachment) => {
+      return this.removeWithSubstanceById(attachment._id);
     });
+
+    return Promise.all(promises);
   };
 
   attachmentSchema.statics.removeWithSubstanceById = async function(id) {

+ 2 - 1
src/server/models/comment.js

@@ -12,9 +12,10 @@ module.exports = function(crowi) {
     revision: { type: ObjectId, ref: 'Revision', index: true },
     comment: { type: String, required: true },
     commentPosition: { type: Number, default: -1 },
-    createdAt: { type: Date, default: Date.now },
     isMarkdown: { type: Boolean, default: false },
     replyTo: { type: ObjectId },
+  }, {
+    timestamps: true,
   });
 
   commentSchema.statics.create = function(pageId, creatorId, revisionId, comment, position, isMarkdown, replyTo) {

+ 1 - 0
src/server/routes/attachment.js

@@ -332,6 +332,7 @@ module.exports = function(crowi, app) {
       await Attachment.removeWithSubstanceById(id);
     }
     catch (err) {
+      logger.error(err);
       return res.status(500).json(ApiResponse.error('Error while deleting file'));
     }
 

+ 7 - 13
src/server/routes/comment.js

@@ -192,24 +192,18 @@ module.exports = function(crowi, app) {
       return res.json(ApiResponse.error('Current user is not accessible to this page.'));
     }
 
+    let updatedComment;
     try {
-      const updatedComment = await Comment.updateCommentsByPageId(comment, isMarkdown, commentId);
-
-      const page = await Page.findOneAndUpdate({ _id: pageId }, {
-        lastUpdateUser: req.user,
-        updatedAt: new Date(),
-      });
-
-      res.json(ApiResponse.success({ comment: updatedComment }));
-
-      const path = page.path;
-
-      // global notification
-      globalNotificationService.notifyComment(updatedComment, path);
+      updatedComment = await Comment.updateCommentsByPageId(comment, isMarkdown, commentId);
     }
     catch (err) {
+      logger.error(err);
       return res.json(ApiResponse.error(err));
     }
+
+    res.json(ApiResponse.success({ comment: updatedComment }));
+
+    // process notification if needed
   };
 
   /**

+ 2 - 0
src/server/service/file-uploader/aws.js

@@ -63,6 +63,8 @@ module.exports = function(crowi) {
       Key: filePath,
     };
 
+    // TODO: ensure not to throw error even when the file does not exist
+
     return s3.deleteObject(params).promise();
   };
 

+ 7 - 5
src/server/service/file-uploader/gridfs.js

@@ -20,6 +20,7 @@ module.exports = function(crowi) {
 
   // create promisified method
   AttachmentFile.promisifiedWrite = util.promisify(AttachmentFile.write).bind(AttachmentFile);
+  AttachmentFile.promisifiedUnlink = util.promisify(AttachmentFile.unlink).bind(AttachmentFile);
 
   lib.deleteFile = async function(attachment) {
     let filenameValue = attachment.fileName;
@@ -30,11 +31,12 @@ module.exports = function(crowi) {
 
     const attachmentFile = await AttachmentFile.findOne({ filename: filenameValue });
 
-    AttachmentFile.unlink({ _id: attachmentFile._id }, (error, unlinkedFile) => {
-      if (error) {
-        throw new Error(error);
-      }
-    });
+    if (attachmentFile == null) {
+      logger.warn(`Any AttachmentFile that relate to the Attachment (${attachment._id.toString()}) does not exist in GridFS`);
+      return;
+    }
+
+    return AttachmentFile.promisifiedUnlink({ _id: attachmentFile._id });
   };
 
   /**

+ 8 - 0
src/server/service/file-uploader/local.js

@@ -31,6 +31,14 @@ module.exports = function(crowi) {
   };
 
   lib.deleteFileByFilePath = async function(filePath) {
+    // check file exists
+    try {
+      fs.statSync(filePath);
+    }
+    catch (err) {
+      logger.warn(`Any AttachmentFile which path is '${filePath}' does not exist in local fs`);
+    }
+
     return fs.unlinkSync(filePath);
   };
 

+ 9 - 0
src/test/global-setup.js

@@ -0,0 +1,9 @@
+const mongoUri = process.env.MONGOLAB_URI || process.env.MONGOHQ_URL || process.env.MONGO_URI || 'mongodb://localhost/growi_test';
+
+const mongoose = require('mongoose');
+
+module.exports = async() => {
+  await mongoose.connect(mongoUri, { useNewUrlParser: true });
+  await mongoose.connection.dropDatabase();
+  await mongoose.disconnect();
+};

+ 2 - 0
src/test/global-teardown.js

@@ -0,0 +1,2 @@
+module.exports = async() => {
+};

+ 0 - 1
src/test/setup.js

@@ -8,7 +8,6 @@ jest.setTimeout(30000); // default 5000
 
 beforeAll(async(done) => {
   await mongoose.connect(mongoUri, { useNewUrlParser: true });
-  await mongoose.connection.dropDatabase();
   done();
 });
 

+ 7 - 1
wercker.yml

@@ -51,13 +51,19 @@ build-prod:
     - script:
       name: install plugins
       code: |
-        yarn add growi-plugin-lsx growi-plugin-pukiwiki-like-linker
+        yarn add growi-plugin-lsx growi-plugin-pukiwiki-like-linker growi-plugin-attachment-refs
+        yarn add -D react-images react-motion
 
     - script:
       name: npm run build:prod:analyze
       code: |
         npm run build:prod:analyze
 
+    - script:
+      name: shrink dependencies for production
+      code: |
+        yarn install --production
+
     - script:
       name: npm run server:prod:ci
       code: |

+ 14 - 13
yarn.lock

@@ -2792,9 +2792,10 @@ code-point-at@^1.0.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
 
-codemirror@^5.42.0:
-  version "5.42.0"
-  resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.42.0.tgz#2d5b640ed009e89dee9ed8a2a778e2a25b65f9eb"
+codemirror@^5.48.4:
+  version "5.48.4"
+  resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.48.4.tgz#4210fbe92be79a88f0eea348fab3ae78da85ce47"
+  integrity sha512-pUhZXDQ6qXSpWdwlgAwHEkd4imA0kf83hINmUEzJpmG80T/XLtDDEzZo8f6PQLuRCcUQhmzqqIo3ZPTRaWByRA==
 
 collapse-white-space@^1.0.2:
   version "1.0.4"
@@ -4055,15 +4056,15 @@ enhanced-resolve@4.1.0, enhanced-resolve@^4.1.0:
     memory-fs "^0.4.0"
     tapable "^1.0.0"
 
-entities@=1.1.2:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
-  integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==
-
 entities@^1.1.1, entities@~1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0"
 
+entities@^2.0.0, entities@~2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4"
+  integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==
+
 env-cmd@^10.0.1:
   version "10.0.1"
   resolved "https://registry.yarnpkg.com/env-cmd/-/env-cmd-10.0.1.tgz#bcaedad78a0172c62113890dd4efec36d2ba0775"
@@ -7598,13 +7599,13 @@ markdown-it-toc-and-anchor-with-slugid@^1.1.4:
     clone "^2.1.0"
     uslug "^1.0.4"
 
-markdown-it@^9.0.1:
-  version "9.0.1"
-  resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-9.0.1.tgz#aafe363c43718720b6575fd10625cde6e4ff2d47"
-  integrity sha512-XC9dMBHg28Xi7y5dPuLjM61upIGPJG8AiHNHYqIaXER2KNnn7eKnM5/sF0ImNnyoV224Ogn9b1Pck8VH4k0bxw==
+markdown-it@^10.0.0:
+  version "10.0.0"
+  resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-10.0.0.tgz#abfc64f141b1722d663402044e43927f1f50a8dc"
+  integrity sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==
   dependencies:
     argparse "^1.0.7"
-    entities "~1.1.1"
+    entities "~2.0.0"
     linkify-it "^2.0.0"
     mdurl "^1.0.1"
     uc.micro "^1.0.5"