@crowi/api 2.0.0-alpha.1 → 2.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hono/handlers/activation.d.ts +3 -3
- package/dist/hono/handlers/admin/users.d.ts +118 -0
- package/dist/hono/handlers/admin/users.js +28 -0
- package/dist/hono/handlers/admin/users.js.map +1 -1
- package/dist/hono/handlers/app.d.ts +1 -0
- package/dist/hono/handlers/app.js +11 -0
- package/dist/hono/handlers/app.js.map +1 -1
- package/dist/hono/handlers/attachment-stream.js +23 -0
- package/dist/hono/handlers/attachment-stream.js.map +1 -1
- package/dist/hono/handlers/draft.js +10 -0
- package/dist/hono/handlers/draft.js.map +1 -1
- package/dist/hono/handlers/emailChange.d.ts +4 -4
- package/dist/hono/handlers/inviteAccept.d.ts +6 -6
- package/dist/hono/handlers/page.d.ts +251 -0
- package/dist/hono/handlers/page.js +123 -6
- package/dist/hono/handlers/page.js.map +1 -1
- package/dist/hono/handlers/passwordReset.d.ts +5 -5
- package/dist/hono/handlers/tokenAuth.d.ts +7 -7
- package/dist/mcp/result.d.ts +42 -16
- package/dist/mcp/result.js +56 -10
- package/dist/mcp/result.js.map +1 -1
- package/dist/mcp/tools/page.js +21 -1
- package/dist/mcp/tools/page.js.map +1 -1
- package/dist/mcp/tools/search.d.ts +12 -0
- package/dist/mcp/tools/search.js +21 -5
- package/dist/mcp/tools/search.js.map +1 -1
- package/dist/migration/helpers.d.ts +13 -0
- package/dist/migration/helpers.js +29 -0
- package/dist/migration/helpers.js.map +1 -0
- package/dist/migration/migrations/files-url-to-attachments.d.ts +35 -0
- package/dist/migration/migrations/files-url-to-attachments.js +291 -0
- package/dist/migration/migrations/files-url-to-attachments.js.map +1 -0
- package/dist/migration/migrations/index.js +4 -0
- package/dist/migration/migrations/index.js.map +1 -1
- package/dist/migration/migrations/published-current-revision.d.ts +47 -0
- package/dist/migration/migrations/published-current-revision.js +90 -0
- package/dist/migration/migrations/published-current-revision.js.map +1 -0
- package/dist/migration/migrations/wikilink-format.d.ts +0 -11
- package/dist/migration/migrations/wikilink-format.js +5 -156
- package/dist/migration/migrations/wikilink-format.js.map +1 -1
- package/dist/migration/migrations/wikilink-html-recover.d.ts +116 -0
- package/dist/migration/migrations/wikilink-html-recover.js +314 -0
- package/dist/migration/migrations/wikilink-html-recover.js.map +1 -0
- package/dist/models/page.d.ts +3 -0
- package/dist/models/page.js +31 -0
- package/dist/models/page.js.map +1 -1
- package/dist/models/user.d.ts +1 -0
- package/dist/models/user.js +40 -21
- package/dist/models/user.js.map +1 -1
- package/dist/renderer/core/headings.d.ts +12 -1
- package/dist/renderer/core/headings.js +48 -8
- package/dist/renderer/core/headings.js.map +1 -1
- package/dist/renderer/pipeline.d.ts +6 -0
- package/dist/renderer/pipeline.js.map +1 -1
- package/dist/util/page-response.js +19 -2
- package/dist/util/page-response.js.map +1 -1
- package/package.json +12 -6
- package/views/mail/layout.mjml +7 -5
- package/dist/common/functions/path2name.d.ts +0 -1
- package/dist/common/functions/path2name.js +0 -22
- package/dist/common/functions/path2name.js.map +0 -1
- package/dist/common/functions/renderIcon.d.ts +0 -1
- package/dist/common/functions/renderIcon.js +0 -9
- package/dist/common/functions/renderIcon.js.map +0 -1
- package/dist/controllers/admin.d.ts +0 -3
- package/dist/controllers/admin.js +0 -474
- package/dist/controllers/admin.js.map +0 -1
- package/dist/controllers/attachment.d.ts +0 -4
- package/dist/controllers/attachment.js +0 -200
- package/dist/controllers/attachment.js.map +0 -1
- package/dist/controllers/backlink.d.ts +0 -3
- package/dist/controllers/backlink.js +0 -42
- package/dist/controllers/backlink.js.map +0 -1
- package/dist/controllers/bookmark.d.ts +0 -3
- package/dist/controllers/bookmark.js +0 -100
- package/dist/controllers/bookmark.js.map +0 -1
- package/dist/controllers/comment.d.ts +0 -3
- package/dist/controllers/comment.js +0 -111
- package/dist/controllers/comment.js.map +0 -1
- package/dist/controllers/index.d.ts +0 -25
- package/dist/controllers/index.js +0 -44
- package/dist/controllers/index.js.map +0 -1
- package/dist/controllers/installer.d.ts +0 -3
- package/dist/controllers/installer.js +0 -48
- package/dist/controllers/installer.js.map +0 -1
- package/dist/controllers/login.d.ts +0 -4
- package/dist/controllers/login.js +0 -438
- package/dist/controllers/login.js.map +0 -1
- package/dist/controllers/logout.d.ts +0 -5
- package/dist/controllers/logout.js +0 -11
- package/dist/controllers/logout.js.map +0 -1
- package/dist/controllers/me.d.ts +0 -4
- package/dist/controllers/me.js +0 -369
- package/dist/controllers/me.js.map +0 -1
- package/dist/controllers/notification.d.ts +0 -3
- package/dist/controllers/notification.js +0 -88
- package/dist/controllers/notification.js.map +0 -1
- package/dist/controllers/page.d.ts +0 -3
- package/dist/controllers/page.js +0 -881
- package/dist/controllers/page.js.map +0 -1
- package/dist/controllers/revision.d.ts +0 -3
- package/dist/controllers/revision.js +0 -91
- package/dist/controllers/revision.js.map +0 -1
- package/dist/controllers/search.d.ts +0 -3
- package/dist/controllers/search.js +0 -93
- package/dist/controllers/search.js.map +0 -1
- package/dist/controllers/share.d.ts +0 -3
- package/dist/controllers/share.js +0 -207
- package/dist/controllers/share.js.map +0 -1
- package/dist/controllers/shareAccess.d.ts +0 -3
- package/dist/controllers/shareAccess.js +0 -28
- package/dist/controllers/shareAccess.js.map +0 -1
- package/dist/controllers/slack.d.ts +0 -3
- package/dist/controllers/slack.js +0 -87
- package/dist/controllers/slack.js.map +0 -1
- package/dist/controllers/tokenAuth.d.ts +0 -10
- package/dist/controllers/tokenAuth.js +0 -292
- package/dist/controllers/tokenAuth.js.map +0 -1
- package/dist/controllers/user.d.ts +0 -3
- package/dist/controllers/user.js +0 -67
- package/dist/controllers/user.js.map +0 -1
- package/dist/controllers/version.d.ts +0 -4
- package/dist/controllers/version.js +0 -19
- package/dist/controllers/version.js.map +0 -1
- package/dist/crowi/express-init.d.ts +0 -4
- package/dist/crowi/express-init.js +0 -101
- package/dist/crowi/express-init.js.map +0 -1
- package/dist/form/admin/app.d.ts +0 -2
- package/dist/form/admin/app.js +0 -9
- package/dist/form/admin/app.js.map +0 -1
- package/dist/form/admin/auth.d.ts +0 -2
- package/dist/form/admin/auth.js +0 -9
- package/dist/form/admin/auth.js.map +0 -1
- package/dist/form/admin/aws.d.ts +0 -2
- package/dist/form/admin/aws.js +0 -13
- package/dist/form/admin/aws.js.map +0 -1
- package/dist/form/admin/github.d.ts +0 -2
- package/dist/form/admin/github.js +0 -15
- package/dist/form/admin/github.js.map +0 -1
- package/dist/form/admin/google.d.ts +0 -2
- package/dist/form/admin/google.js +0 -13
- package/dist/form/admin/google.js.map +0 -1
- package/dist/form/admin/mail.d.ts +0 -2
- package/dist/form/admin/mail.js +0 -13
- package/dist/form/admin/mail.js.map +0 -1
- package/dist/form/admin/sec.d.ts +0 -2
- package/dist/form/admin/sec.js +0 -10
- package/dist/form/admin/sec.js.map +0 -1
- package/dist/form/admin/slackSetting.d.ts +0 -2
- package/dist/form/admin/slackSetting.js +0 -13
- package/dist/form/admin/slackSetting.js.map +0 -1
- package/dist/form/admin/userEdit.d.ts +0 -2
- package/dist/form/admin/userEdit.js +0 -9
- package/dist/form/admin/userEdit.js.map +0 -1
- package/dist/form/admin/userInvite.d.ts +0 -2
- package/dist/form/admin/userInvite.js +0 -9
- package/dist/form/admin/userInvite.js.map +0 -1
- package/dist/form/comment.d.ts +0 -2
- package/dist/form/comment.js +0 -9
- package/dist/form/comment.js.map +0 -1
- package/dist/form/index.d.ts +0 -25
- package/dist/form/index.js +0 -48
- package/dist/form/index.js.map +0 -1
- package/dist/form/invited.d.ts +0 -2
- package/dist/form/invited.js +0 -13
- package/dist/form/invited.js.map +0 -1
- package/dist/form/login.d.ts +0 -2
- package/dist/form/login.js +0 -11
- package/dist/form/login.js.map +0 -1
- package/dist/form/me/apiToken.d.ts +0 -2
- package/dist/form/me/apiToken.js +0 -9
- package/dist/form/me/apiToken.js.map +0 -1
- package/dist/form/me/password.d.ts +0 -2
- package/dist/form/me/password.js +0 -11
- package/dist/form/me/password.js.map +0 -1
- package/dist/form/me/user.d.ts +0 -2
- package/dist/form/me/user.js +0 -9
- package/dist/form/me/user.js.map +0 -1
- package/dist/form/register.d.ts +0 -2
- package/dist/form/register.js +0 -13
- package/dist/form/register.js.map +0 -1
- package/dist/form/revision.d.ts +0 -2
- package/dist/form/revision.js +0 -13
- package/dist/form/revision.js.map +0 -1
- package/dist/hono/handlers/admin/share.d.ts +0 -106
- package/dist/hono/handlers/admin/share.js +0 -55
- package/dist/hono/handlers/admin/share.js.map +0 -1
- package/dist/middlewares/accessTokenParser.d.ts +0 -4
- package/dist/middlewares/accessTokenParser.js +0 -29
- package/dist/middlewares/accessTokenParser.js.map +0 -1
- package/dist/middlewares/adminRequired.d.ts +0 -10
- package/dist/middlewares/adminRequired.js +0 -35
- package/dist/middlewares/adminRequired.js.map +0 -1
- package/dist/middlewares/applicationInstalled.d.ts +0 -3
- package/dist/middlewares/applicationInstalled.js +0 -20
- package/dist/middlewares/applicationInstalled.js.map +0 -1
- package/dist/middlewares/applicationNotInstalled.d.ts +0 -3
- package/dist/middlewares/applicationNotInstalled.js +0 -13
- package/dist/middlewares/applicationNotInstalled.js.map +0 -1
- package/dist/middlewares/basicAuth.d.ts +0 -4
- package/dist/middlewares/basicAuth.js +0 -23
- package/dist/middlewares/basicAuth.js.map +0 -1
- package/dist/middlewares/csrfVerify.d.ts +0 -4
- package/dist/middlewares/csrfVerify.js +0 -24
- package/dist/middlewares/csrfVerify.js.map +0 -1
- package/dist/middlewares/encodeSpace.d.ts +0 -3
- package/dist/middlewares/encodeSpace.js +0 -14
- package/dist/middlewares/encodeSpace.js.map +0 -1
- package/dist/middlewares/fileAccessRightOrLoginRequired.d.ts +0 -4
- package/dist/middlewares/fileAccessRightOrLoginRequired.js +0 -29
- package/dist/middlewares/fileAccessRightOrLoginRequired.js.map +0 -1
- package/dist/middlewares/index.d.ts +0 -16
- package/dist/middlewares/index.js +0 -30
- package/dist/middlewares/index.js.map +0 -1
- package/dist/middlewares/jwtAdminRequired.d.ts +0 -8
- package/dist/middlewares/jwtAdminRequired.js +0 -35
- package/dist/middlewares/jwtAdminRequired.js.map +0 -1
- package/dist/middlewares/jwtAuth.d.ts +0 -4
- package/dist/middlewares/jwtAuth.js +0 -104
- package/dist/middlewares/jwtAuth.js.map +0 -1
- package/dist/middlewares/loginChecker.d.ts +0 -4
- package/dist/middlewares/loginChecker.js +0 -32
- package/dist/middlewares/loginChecker.js.map +0 -1
- package/dist/middlewares/loginRequired.d.ts +0 -4
- package/dist/middlewares/loginRequired.js +0 -88
- package/dist/middlewares/loginRequired.js.map +0 -1
- package/dist/routes/admin.d.ts +0 -4
- package/dist/routes/admin.js +0 -17
- package/dist/routes/admin.js.map +0 -1
- package/dist/routes/api/admin.d.ts +0 -4
- package/dist/routes/api/admin.js +0 -37
- package/dist/routes/api/admin.js.map +0 -1
- package/dist/routes/api/attachment.d.ts +0 -4
- package/dist/routes/api/attachment.js +0 -19
- package/dist/routes/api/attachment.js.map +0 -1
- package/dist/routes/api/bookmark.d.ts +0 -4
- package/dist/routes/api/bookmark.js +0 -15
- package/dist/routes/api/bookmark.js.map +0 -1
- package/dist/routes/api/comment.d.ts +0 -4
- package/dist/routes/api/comment.js +0 -14
- package/dist/routes/api/comment.js.map +0 -1
- package/dist/routes/api/index.d.ts +0 -4
- package/dist/routes/api/index.js +0 -36
- package/dist/routes/api/index.js.map +0 -1
- package/dist/routes/api/like.d.ts +0 -4
- package/dist/routes/api/like.js +0 -13
- package/dist/routes/api/like.js.map +0 -1
- package/dist/routes/api/notification.d.ts +0 -4
- package/dist/routes/api/notification.js +0 -15
- package/dist/routes/api/notification.js.map +0 -1
- package/dist/routes/api/page.d.ts +0 -4
- package/dist/routes/api/page.js +0 -24
- package/dist/routes/api/page.js.map +0 -1
- package/dist/routes/api/revision.d.ts +0 -4
- package/dist/routes/api/revision.js +0 -14
- package/dist/routes/api/revision.js.map +0 -1
- package/dist/routes/api/share.d.ts +0 -4
- package/dist/routes/api/share.js +0 -16
- package/dist/routes/api/share.js.map +0 -1
- package/dist/routes/api/version.d.ts +0 -4
- package/dist/routes/api/version.js +0 -10
- package/dist/routes/api/version.js.map +0 -1
- package/dist/routes/index.d.ts +0 -4
- package/dist/routes/index.js +0 -71
- package/dist/routes/index.js.map +0 -1
- package/dist/routes/login.d.ts +0 -4
- package/dist/routes/login.js +0 -18
- package/dist/routes/login.js.map +0 -1
- package/dist/routes/me.d.ts +0 -4
- package/dist/routes/me.js +0 -24
- package/dist/routes/me.js.map +0 -1
- package/dist/routes/ts-rest/admin/app.d.ts +0 -4
- package/dist/routes/ts-rest/admin/app.js +0 -67
- package/dist/routes/ts-rest/admin/app.js.map +0 -1
- package/dist/routes/ts-rest/admin/auth.d.ts +0 -4
- package/dist/routes/ts-rest/admin/auth.js +0 -95
- package/dist/routes/ts-rest/admin/auth.js.map +0 -1
- package/dist/routes/ts-rest/admin/index.d.ts +0 -10
- package/dist/routes/ts-rest/admin/index.js +0 -35
- package/dist/routes/ts-rest/admin/index.js.map +0 -1
- package/dist/routes/ts-rest/admin/mail.d.ts +0 -4
- package/dist/routes/ts-rest/admin/mail.js +0 -156
- package/dist/routes/ts-rest/admin/mail.js.map +0 -1
- package/dist/routes/ts-rest/admin/plugins.d.ts +0 -4
- package/dist/routes/ts-rest/admin/plugins.js +0 -317
- package/dist/routes/ts-rest/admin/plugins.js.map +0 -1
- package/dist/routes/ts-rest/admin/search.d.ts +0 -4
- package/dist/routes/ts-rest/admin/search.js +0 -67
- package/dist/routes/ts-rest/admin/search.js.map +0 -1
- package/dist/routes/ts-rest/admin/security.d.ts +0 -4
- package/dist/routes/ts-rest/admin/security.js +0 -114
- package/dist/routes/ts-rest/admin/security.js.map +0 -1
- package/dist/routes/ts-rest/admin/share.d.ts +0 -4
- package/dist/routes/ts-rest/admin/share.js +0 -69
- package/dist/routes/ts-rest/admin/share.js.map +0 -1
- package/dist/routes/ts-rest/admin/storage.d.ts +0 -4
- package/dist/routes/ts-rest/admin/storage.js +0 -59
- package/dist/routes/ts-rest/admin/storage.js.map +0 -1
- package/dist/routes/ts-rest/admin/users.d.ts +0 -4
- package/dist/routes/ts-rest/admin/users.js +0 -215
- package/dist/routes/ts-rest/admin/users.js.map +0 -1
- package/dist/routes/ts-rest/adminCrypto.d.ts +0 -4
- package/dist/routes/ts-rest/adminCrypto.js +0 -111
- package/dist/routes/ts-rest/adminCrypto.js.map +0 -1
- package/dist/routes/ts-rest/app.d.ts +0 -4
- package/dist/routes/ts-rest/app.js +0 -23
- package/dist/routes/ts-rest/app.js.map +0 -1
- package/dist/routes/ts-rest/attachment.d.ts +0 -4
- package/dist/routes/ts-rest/attachment.js +0 -830
- package/dist/routes/ts-rest/attachment.js.map +0 -1
- package/dist/routes/ts-rest/auth.d.ts +0 -4
- package/dist/routes/ts-rest/auth.js +0 -70
- package/dist/routes/ts-rest/auth.js.map +0 -1
- package/dist/routes/ts-rest/autocomplete.d.ts +0 -30
- package/dist/routes/ts-rest/autocomplete.js +0 -189
- package/dist/routes/ts-rest/autocomplete.js.map +0 -1
- package/dist/routes/ts-rest/backlink.d.ts +0 -4
- package/dist/routes/ts-rest/backlink.js +0 -106
- package/dist/routes/ts-rest/backlink.js.map +0 -1
- package/dist/routes/ts-rest/bookmark.d.ts +0 -4
- package/dist/routes/ts-rest/bookmark.js +0 -189
- package/dist/routes/ts-rest/bookmark.js.map +0 -1
- package/dist/routes/ts-rest/comment.d.ts +0 -4
- package/dist/routes/ts-rest/comment.js +0 -217
- package/dist/routes/ts-rest/comment.js.map +0 -1
- package/dist/routes/ts-rest/draft.d.ts +0 -22
- package/dist/routes/ts-rest/draft.js +0 -200
- package/dist/routes/ts-rest/draft.js.map +0 -1
- package/dist/routes/ts-rest/index.d.ts +0 -4
- package/dist/routes/ts-rest/index.js +0 -103
- package/dist/routes/ts-rest/index.js.map +0 -1
- package/dist/routes/ts-rest/installer.d.ts +0 -4
- package/dist/routes/ts-rest/installer.js +0 -77
- package/dist/routes/ts-rest/installer.js.map +0 -1
- package/dist/routes/ts-rest/me.d.ts +0 -4
- package/dist/routes/ts-rest/me.js +0 -410
- package/dist/routes/ts-rest/me.js.map +0 -1
- package/dist/routes/ts-rest/notification.d.ts +0 -4
- package/dist/routes/ts-rest/notification.js +0 -241
- package/dist/routes/ts-rest/notification.js.map +0 -1
- package/dist/routes/ts-rest/page-collab.d.ts +0 -29
- package/dist/routes/ts-rest/page-collab.js +0 -90
- package/dist/routes/ts-rest/page-collab.js.map +0 -1
- package/dist/routes/ts-rest/page-preview.d.ts +0 -26
- package/dist/routes/ts-rest/page-preview.js +0 -80
- package/dist/routes/ts-rest/page-preview.js.map +0 -1
- package/dist/routes/ts-rest/page.d.ts +0 -4
- package/dist/routes/ts-rest/page.js +0 -676
- package/dist/routes/ts-rest/page.js.map +0 -1
- package/dist/routes/ts-rest/presence.d.ts +0 -30
- package/dist/routes/ts-rest/presence.js +0 -155
- package/dist/routes/ts-rest/presence.js.map +0 -1
- package/dist/routes/ts-rest/revision.d.ts +0 -4
- package/dist/routes/ts-rest/revision.js +0 -240
- package/dist/routes/ts-rest/revision.js.map +0 -1
- package/dist/routes/ts-rest/search.d.ts +0 -4
- package/dist/routes/ts-rest/search.js +0 -121
- package/dist/routes/ts-rest/search.js.map +0 -1
- package/dist/routes/ts-rest/tokenAuth.d.ts +0 -4
- package/dist/routes/ts-rest/tokenAuth.js +0 -94
- package/dist/routes/ts-rest/tokenAuth.js.map +0 -1
- package/dist/routes/ts-rest/user.d.ts +0 -4
- package/dist/routes/ts-rest/user.js +0 -307
- package/dist/routes/ts-rest/user.js.map +0 -1
- package/dist/types/express.d.ts +0 -34
- package/dist/types/express.js +0 -50
- package/dist/types/express.js.map +0 -1
- package/dist/util/accessTokenParser.d.ts +0 -1
- package/dist/util/accessTokenParser.js +0 -34
- package/dist/util/accessTokenParser.js.map +0 -1
- package/dist/util/apiPaginate.d.ts +0 -11
- package/dist/util/apiPaginate.js +0 -33
- package/dist/util/apiPaginate.js.map +0 -1
- package/dist/util/apiResponse.d.ts +0 -9
- package/dist/util/apiResponse.js +0 -23
- package/dist/util/apiResponse.js.map +0 -1
- package/dist/util/auth.d.ts +0 -11
- package/dist/util/auth.js +0 -48
- package/dist/util/auth.js.map +0 -1
- package/dist/util/aws-config-migration.d.ts +0 -11
- package/dist/util/aws-config-migration.js +0 -68
- package/dist/util/aws-config-migration.js.map +0 -1
- package/dist/util/formUtil.d.ts +0 -2
- package/dist/util/formUtil.js +0 -15
- package/dist/util/formUtil.js.map +0 -1
- package/dist/util/githubAuth.d.ts +0 -2
- package/dist/util/githubAuth.js +0 -82
- package/dist/util/githubAuth.js.map +0 -1
- package/dist/util/googleAuth.d.ts +0 -2
- package/dist/util/googleAuth.js +0 -85
- package/dist/util/googleAuth.js.map +0 -1
- package/dist/util/mailer.d.ts +0 -7
- package/dist/util/mailer.js +0 -98
- package/dist/util/mailer.js.map +0 -1
- package/dist/util/page-status-migration.d.ts +0 -23
- package/dist/util/page-status-migration.js +0 -48
- package/dist/util/page-status-migration.js.map +0 -1
- package/dist/util/ssr.d.ts +0 -3
- package/dist/util/ssr.js +0 -9
- package/dist/util/ssr.js.map +0 -1
- package/dist/util/view.d.ts +0 -10
- package/dist/util/view.js +0 -99
- package/dist/util/view.js.map +0 -1
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.wikilinkFormat = exports.WIKILINK_DETECTION_REGEX =
|
|
3
|
+
exports.wikilinkFormat = exports.WIKILINK_DETECTION_REGEX = void 0;
|
|
4
4
|
exports.bodyHasRewritableWikilink = bodyHasRewritableWikilink;
|
|
5
5
|
exports.shouldRewriteWikilink = shouldRewriteWikilink;
|
|
6
6
|
exports.rewriteAndDetect = rewriteAndDetect;
|
|
7
7
|
exports.rewriteWikilinks = rewriteWikilinks;
|
|
8
|
+
const api_contract_1 = require("@crowi/api-contract");
|
|
8
9
|
const page_1 = require("../../models/page");
|
|
10
|
+
const helpers_1 = require("../helpers");
|
|
9
11
|
const types_1 = require("../types");
|
|
10
12
|
/**
|
|
11
13
|
* RFC-0008 §10.2 step 4 / §4.3.1 — `wikilink-format` (preflight layer).
|
|
@@ -29,129 +31,6 @@ const types_1 = require("../types");
|
|
|
29
31
|
* The textual conversion logic below is moved verbatim from the old command so
|
|
30
32
|
* the rewrite output is byte-identical to the legacy migrator.
|
|
31
33
|
*/
|
|
32
|
-
/**
|
|
33
|
-
* HTML5 element name set used to reject `</foo>` matches whose first path
|
|
34
|
-
* segment is actually a closing HTML tag. Source:
|
|
35
|
-
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element — the full
|
|
36
|
-
* standard element list as of the HTML Living Standard.
|
|
37
|
-
*
|
|
38
|
-
* Kept as a top-level `Set<string>` so detection runs O(1) per match.
|
|
39
|
-
* `h1`..`h6` are listed explicitly because the regex captures `foo` for
|
|
40
|
-
* `</foo>` and we want both `</h1>` and `</h6>` to be rejected.
|
|
41
|
-
*/
|
|
42
|
-
exports.KNOWN_HTML_ELEMENTS = new Set([
|
|
43
|
-
'a',
|
|
44
|
-
'abbr',
|
|
45
|
-
'address',
|
|
46
|
-
'area',
|
|
47
|
-
'article',
|
|
48
|
-
'aside',
|
|
49
|
-
'audio',
|
|
50
|
-
'b',
|
|
51
|
-
'base',
|
|
52
|
-
'bdi',
|
|
53
|
-
'bdo',
|
|
54
|
-
'blockquote',
|
|
55
|
-
'body',
|
|
56
|
-
'br',
|
|
57
|
-
'button',
|
|
58
|
-
'canvas',
|
|
59
|
-
'caption',
|
|
60
|
-
'cite',
|
|
61
|
-
'code',
|
|
62
|
-
'col',
|
|
63
|
-
'colgroup',
|
|
64
|
-
'data',
|
|
65
|
-
'datalist',
|
|
66
|
-
'dd',
|
|
67
|
-
'del',
|
|
68
|
-
'details',
|
|
69
|
-
'dfn',
|
|
70
|
-
'dialog',
|
|
71
|
-
'div',
|
|
72
|
-
'dl',
|
|
73
|
-
'dt',
|
|
74
|
-
'em',
|
|
75
|
-
'embed',
|
|
76
|
-
'fieldset',
|
|
77
|
-
'figcaption',
|
|
78
|
-
'figure',
|
|
79
|
-
'footer',
|
|
80
|
-
'form',
|
|
81
|
-
'h1',
|
|
82
|
-
'h2',
|
|
83
|
-
'h3',
|
|
84
|
-
'h4',
|
|
85
|
-
'h5',
|
|
86
|
-
'h6',
|
|
87
|
-
'head',
|
|
88
|
-
'header',
|
|
89
|
-
'hgroup',
|
|
90
|
-
'hr',
|
|
91
|
-
'html',
|
|
92
|
-
'i',
|
|
93
|
-
'iframe',
|
|
94
|
-
'img',
|
|
95
|
-
'input',
|
|
96
|
-
'ins',
|
|
97
|
-
'kbd',
|
|
98
|
-
'label',
|
|
99
|
-
'legend',
|
|
100
|
-
'li',
|
|
101
|
-
'link',
|
|
102
|
-
'main',
|
|
103
|
-
'map',
|
|
104
|
-
'mark',
|
|
105
|
-
'menu',
|
|
106
|
-
'meta',
|
|
107
|
-
'meter',
|
|
108
|
-
'nav',
|
|
109
|
-
'noscript',
|
|
110
|
-
'object',
|
|
111
|
-
'ol',
|
|
112
|
-
'optgroup',
|
|
113
|
-
'option',
|
|
114
|
-
'output',
|
|
115
|
-
'p',
|
|
116
|
-
'picture',
|
|
117
|
-
'pre',
|
|
118
|
-
'progress',
|
|
119
|
-
'q',
|
|
120
|
-
'rp',
|
|
121
|
-
'rt',
|
|
122
|
-
'ruby',
|
|
123
|
-
's',
|
|
124
|
-
'samp',
|
|
125
|
-
'script',
|
|
126
|
-
'section',
|
|
127
|
-
'select',
|
|
128
|
-
'slot',
|
|
129
|
-
'small',
|
|
130
|
-
'source',
|
|
131
|
-
'span',
|
|
132
|
-
'strong',
|
|
133
|
-
'style',
|
|
134
|
-
'sub',
|
|
135
|
-
'summary',
|
|
136
|
-
'sup',
|
|
137
|
-
'table',
|
|
138
|
-
'tbody',
|
|
139
|
-
'td',
|
|
140
|
-
'template',
|
|
141
|
-
'textarea',
|
|
142
|
-
'tfoot',
|
|
143
|
-
'th',
|
|
144
|
-
'thead',
|
|
145
|
-
'time',
|
|
146
|
-
'title',
|
|
147
|
-
'tr',
|
|
148
|
-
'track',
|
|
149
|
-
'u',
|
|
150
|
-
'ul',
|
|
151
|
-
'var',
|
|
152
|
-
'video',
|
|
153
|
-
'wbr',
|
|
154
|
-
]);
|
|
155
34
|
/**
|
|
156
35
|
* v1 angle-bracket internal link form. The capture group grabs the path-style
|
|
157
36
|
* payload (starts with `/`, no whitespace, no `<` / `>` / `|` other than the
|
|
@@ -215,7 +94,7 @@ function shouldRewriteWikilink(innerPath) {
|
|
|
215
94
|
// Only reject lowercase-ASCII first segments that are real HTML elements.
|
|
216
95
|
if (!/^[a-z][a-z0-9]*$/.test(firstSegment))
|
|
217
96
|
return true;
|
|
218
|
-
return !
|
|
97
|
+
return !api_contract_1.KNOWN_HTML_ELEMENTS.has(firstSegment);
|
|
219
98
|
}
|
|
220
99
|
/**
|
|
221
100
|
* Single-pass detect-and-rewrite. Returns the rewritten body together with the
|
|
@@ -246,36 +125,6 @@ function rewriteAndDetect(body) {
|
|
|
246
125
|
function rewriteWikilinks(body) {
|
|
247
126
|
return rewriteAndDetect(body).body;
|
|
248
127
|
}
|
|
249
|
-
/**
|
|
250
|
-
* Resolve which user is recorded as the author of every rewritten revision.
|
|
251
|
-
* The `updatePage`-equivalent path (`rewritePageBody`) ultimately calls
|
|
252
|
-
* `Revision.prepareRevision`, which **throws** when handed a falsy user, so a
|
|
253
|
-
* preflight rewrite MUST resolve a real acting user up front rather than rely
|
|
254
|
-
* on per-page `lastUpdateUser`/`creator` (those can dangle to a deleted user).
|
|
255
|
-
*
|
|
256
|
-
* Order, mirroring the legacy `migrate-wikilink` command:
|
|
257
|
-
* 1. `process.env.CROWI_MIGRATE_USER` — interpreted as an email; the named
|
|
258
|
-
* user must exist.
|
|
259
|
-
* 2. otherwise the oldest admin user (`{ admin: true }` sorted by createdAt),
|
|
260
|
-
* deterministic across re-runs.
|
|
261
|
-
*
|
|
262
|
-
* Throws when neither yields a user so the operator gets a clear error instead
|
|
263
|
-
* of a per-page `user should have _id` failure deep inside the rewrite.
|
|
264
|
-
*/
|
|
265
|
-
async function resolveActingUserId(ctx) {
|
|
266
|
-
const User = ctx.crowi.model('User');
|
|
267
|
-
const explicit = process.env.CROWI_MIGRATE_USER;
|
|
268
|
-
if (explicit) {
|
|
269
|
-
const named = await User.findOne({ email: explicit }).select('_id').lean().exec();
|
|
270
|
-
if (named)
|
|
271
|
-
return String(named._id);
|
|
272
|
-
throw new Error(`CROWI_MIGRATE_USER='${explicit}' but no user with that email exists.`);
|
|
273
|
-
}
|
|
274
|
-
const admin = await User.findOne({ admin: true }).sort({ createdAt: 1 }).select('_id').lean().exec();
|
|
275
|
-
if (admin)
|
|
276
|
-
return String(admin._id);
|
|
277
|
-
throw new Error('wikilink-format: no admin user found; set CROWI_MIGRATE_USER=<email> or create an admin user first.');
|
|
278
|
-
}
|
|
279
128
|
/**
|
|
280
129
|
* Walk every published page, keep those whose current revision body holds a
|
|
281
130
|
* genuine legacy wikilink (`bodyHasRewritableWikilink` — the same full
|
|
@@ -394,7 +243,7 @@ exports.wikilinkFormat = (0, types_1.defineMigration)({
|
|
|
394
243
|
const pages = await collectRewritablePages(ctx);
|
|
395
244
|
return { name: 'rewrite-wikilink', transformed: 0, stats: { wouldRewrite: pages.length } };
|
|
396
245
|
}
|
|
397
|
-
const actingUserId = await resolveActingUserId(ctx);
|
|
246
|
+
const actingUserId = await (0, helpers_1.resolveActingUserId)(ctx, 'wikilink-format');
|
|
398
247
|
const pages = await collectRewritablePages(ctx);
|
|
399
248
|
ctx.progress.setTotal(pages.length);
|
|
400
249
|
let rewritten = 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wikilink-format.js","sourceRoot":"","sources":["../../../src/migration/migrations/wikilink-format.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"wikilink-format.js","sourceRoot":"","sources":["../../../src/migration/migrations/wikilink-format.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `wikilink-html-recover` (preflight layer) — undo the `wikilink-format`
|
|
3
|
+
* close-tag misfire.
|
|
4
|
+
*
|
|
5
|
+
* Before `font` / `center` / `marquee` / `blink` / `applet` were added to
|
|
6
|
+
* `KNOWN_HTML_ELEMENTS`, `wikilink-format` mistook the deprecated HTML close
|
|
7
|
+
* tags `</font>` etc. for v1 angle-bracket wikilinks and rewrote them to
|
|
8
|
+
* `[[/font]]` (§A). `wikilink-format` is recorded as applied and never
|
|
9
|
+
* re-runs, and the corrupted `[[/font]]` form no longer matches its detection
|
|
10
|
+
* regex, so it does not self-heal. This migration walks every published page
|
|
11
|
+
* and reverts the corrupted form `[[/<x>]]` back to the close tag `</x>` when:
|
|
12
|
+
*
|
|
13
|
+
* - `x` is a single path segment (no `/` inside), AND
|
|
14
|
+
* - `x` has no `|alias` segment, AND
|
|
15
|
+
* - `x` is one of the FIVE deprecated tags the misfire could have produced.
|
|
16
|
+
*
|
|
17
|
+
* Scope is the 5 tags, NOT every known HTML element: those 5 were the ONLY
|
|
18
|
+
* names absent from `KNOWN_HTML_ELEMENTS` when `wikilink-format` ran, so they
|
|
19
|
+
* are the only `</x>` that could ever have been mis-rewritten to `[[/x]]`.
|
|
20
|
+
* `section` / `div` / `br` / `img` / etc. were always known and never rewritten,
|
|
21
|
+
* so a `[[/section]]` in real data is a GENUINE wikilink and must be preserved.
|
|
22
|
+
*
|
|
23
|
+
* Genuine wikilinks are otherwise preserved too: `[[/foo/bar]]` (multi-segment),
|
|
24
|
+
* `[[/font|alias]]` (aliased), `[[/Font]]` (uppercase → case-sensitive page
|
|
25
|
+
* name), and `[[/wiki-page]]` (non-recoverable name) are all left untouched.
|
|
26
|
+
*
|
|
27
|
+
* ── Inherent ambiguity ───────────────────────────────────────────────
|
|
28
|
+
* `[[/font]]` could be a corrupted `</font>` OR a genuine wikilink to a real
|
|
29
|
+
* page literally at `/font`. They are indistinguishable from the text alone.
|
|
30
|
+
* We resolve this conservatively: a `[[/<x>]]` whose `/<x>` matches a **live
|
|
31
|
+
* content page** (published, not a redirect stub) is NOT reverted — it is
|
|
32
|
+
* reported by `detect` so an operator can decide manually. The revert therefore
|
|
33
|
+
* only touches occurrences that have no same-named live page to be mistaken for.
|
|
34
|
+
* Pages literally named after a deprecated tag (`/font`, `/center`, …) are very
|
|
35
|
+
* rare, but an absent-page `[[/font]]` is still reverted — see the docs Caution.
|
|
36
|
+
* ─────────────────────────────────────────────────────────────────────
|
|
37
|
+
*
|
|
38
|
+
* Like `wikilink-format`, every body rewrite routes through
|
|
39
|
+
* `ctx.rewritePageBody` (the `updatePage`-equivalent path) so `yjsState` /
|
|
40
|
+
* `yjsCheckpointAt` are nulled and an active editor's stale `Y.Doc` cannot
|
|
41
|
+
* silently revert the recovery (RFC-0008 §4.3.1).
|
|
42
|
+
*
|
|
43
|
+
* Idempotent: once reverted, `</x>` no longer matches this migration's
|
|
44
|
+
* detection regex (it scans for `[[/...]]`, not `</...>`), and a re-run of
|
|
45
|
+
* `wikilink-format` leaves `</x>` alone because `x` is now in
|
|
46
|
+
* `KNOWN_HTML_ELEMENTS`.
|
|
47
|
+
*/
|
|
48
|
+
/**
|
|
49
|
+
* The five deprecated/obsolete presentational tags absent from
|
|
50
|
+
* `KNOWN_HTML_ELEMENTS` when `wikilink-format` first ran — the ONLY close tags
|
|
51
|
+
* the misfire could have rewritten to `[[/x]]`. Recovery is scoped to exactly
|
|
52
|
+
* these so a genuine single-segment wikilink to any other element-named page
|
|
53
|
+
* (`[[/section]]`, `[[/div]]`, `[[/br]]`) is never destroyed.
|
|
54
|
+
*/
|
|
55
|
+
export declare const RECOVERABLE_DEPRECATED_TAGS: ReadonlySet<string>;
|
|
56
|
+
/**
|
|
57
|
+
* Matches a corrupted-wikilink candidate `[[/<segment>]]` with a single
|
|
58
|
+
* path segment and no alias. The capture group grabs the bare segment
|
|
59
|
+
* (`font` in `[[/font]]`). The `[^[\]|/]+` class excludes `[`, `]`, `|`, and
|
|
60
|
+
* `/`, so multi-segment (`[[/foo/bar]]`) and aliased (`[[/font|x]]`) forms
|
|
61
|
+
* never match here — only `shouldRecoverSegment` then filters by tag name.
|
|
62
|
+
*/
|
|
63
|
+
export declare const WIKILINK_HTML_CANDIDATE_REGEX: RegExp;
|
|
64
|
+
/**
|
|
65
|
+
* True iff `[[/<segment>]]` should be reverted to `</segment>`: the segment is
|
|
66
|
+
* a lowercase-ASCII identifier that is one of the FIVE deprecated tags the
|
|
67
|
+
* misfire could have produced. Uppercase (`/Font`), non-deprecated element
|
|
68
|
+
* names (`/section`, `/div`), and non-HTML names (`/wiki`) are genuine
|
|
69
|
+
* wikilinks and are left alone.
|
|
70
|
+
*/
|
|
71
|
+
export declare function shouldRecoverSegment(segment: string): boolean;
|
|
72
|
+
/** A single corrupted occurrence located in a body. */
|
|
73
|
+
export interface RecoverableOccurrence {
|
|
74
|
+
/** The full raw match, e.g. `[[/font]]`. */
|
|
75
|
+
raw: string;
|
|
76
|
+
/** The deprecated HTML tag name, e.g. `font`. */
|
|
77
|
+
element: string;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Single-pass scan: locate every recoverable `[[/<deprecated-tag>]]` occurrence
|
|
81
|
+
* in `body`. Pure — no rewrite is applied here (the rewrite happens in
|
|
82
|
+
* `rewriteBody` after same-name page collisions have been resolved
|
|
83
|
+
* per-occurrence).
|
|
84
|
+
*/
|
|
85
|
+
export declare function detectRecoverable(body: string): RecoverableOccurrence[];
|
|
86
|
+
/**
|
|
87
|
+
* Rewrite `body`, reverting `[[/<x>]]` → `</x>` for every recoverable element.
|
|
88
|
+
* Elements in `skip` (those that collide with a live same-named page) are left
|
|
89
|
+
* untouched. Returns the input by reference when nothing changed so callers can
|
|
90
|
+
* cheap-skip.
|
|
91
|
+
*/
|
|
92
|
+
export declare function rewriteBody(body: string, skip: ReadonlySet<string>): string;
|
|
93
|
+
/**
|
|
94
|
+
* A skipped (collision) occurrence: the deprecated tag that was left as
|
|
95
|
+
* `[[/<element>]]` because a live same-named page exists, plus the page that
|
|
96
|
+
* holds the corrupted markup so an operator can open it from the report.
|
|
97
|
+
*/
|
|
98
|
+
export interface CollisionRecord {
|
|
99
|
+
/** The deprecated tag name left untouched, e.g. `font`. */
|
|
100
|
+
element: string;
|
|
101
|
+
/** `_id` of the page whose body still carries `[[/<element>]]`. */
|
|
102
|
+
pageId: string;
|
|
103
|
+
/** Path of that holding page (from the current revision), if available. */
|
|
104
|
+
pagePath?: string;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Render collision records into an operator-actionable string that names the
|
|
108
|
+
* holding page(s) per element, e.g.
|
|
109
|
+
* `/font (in /docs/setup, /guide); /center (in /notes)`. The element→pages
|
|
110
|
+
* mapping is preserved so the operator knows exactly which pages to open from
|
|
111
|
+
* the `migrate plan` output / boot warn log. Elements are sorted; per-element
|
|
112
|
+
* pages prefer the page path, falling back to the page id when the revision
|
|
113
|
+
* carried no path.
|
|
114
|
+
*/
|
|
115
|
+
export declare function formatCollisions(collisions: readonly CollisionRecord[]): string;
|
|
116
|
+
export declare const wikilinkHtmlRecover: import("../types").MigrationDefinition;
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.wikilinkHtmlRecover = exports.WIKILINK_HTML_CANDIDATE_REGEX = exports.RECOVERABLE_DEPRECATED_TAGS = void 0;
|
|
4
|
+
exports.shouldRecoverSegment = shouldRecoverSegment;
|
|
5
|
+
exports.detectRecoverable = detectRecoverable;
|
|
6
|
+
exports.rewriteBody = rewriteBody;
|
|
7
|
+
exports.formatCollisions = formatCollisions;
|
|
8
|
+
const page_1 = require("../../models/page");
|
|
9
|
+
const types_1 = require("../types");
|
|
10
|
+
const published_current_revision_1 = require("./published-current-revision");
|
|
11
|
+
const helpers_1 = require("../helpers");
|
|
12
|
+
/**
|
|
13
|
+
* `wikilink-html-recover` (preflight layer) — undo the `wikilink-format`
|
|
14
|
+
* close-tag misfire.
|
|
15
|
+
*
|
|
16
|
+
* Before `font` / `center` / `marquee` / `blink` / `applet` were added to
|
|
17
|
+
* `KNOWN_HTML_ELEMENTS`, `wikilink-format` mistook the deprecated HTML close
|
|
18
|
+
* tags `</font>` etc. for v1 angle-bracket wikilinks and rewrote them to
|
|
19
|
+
* `[[/font]]` (§A). `wikilink-format` is recorded as applied and never
|
|
20
|
+
* re-runs, and the corrupted `[[/font]]` form no longer matches its detection
|
|
21
|
+
* regex, so it does not self-heal. This migration walks every published page
|
|
22
|
+
* and reverts the corrupted form `[[/<x>]]` back to the close tag `</x>` when:
|
|
23
|
+
*
|
|
24
|
+
* - `x` is a single path segment (no `/` inside), AND
|
|
25
|
+
* - `x` has no `|alias` segment, AND
|
|
26
|
+
* - `x` is one of the FIVE deprecated tags the misfire could have produced.
|
|
27
|
+
*
|
|
28
|
+
* Scope is the 5 tags, NOT every known HTML element: those 5 were the ONLY
|
|
29
|
+
* names absent from `KNOWN_HTML_ELEMENTS` when `wikilink-format` ran, so they
|
|
30
|
+
* are the only `</x>` that could ever have been mis-rewritten to `[[/x]]`.
|
|
31
|
+
* `section` / `div` / `br` / `img` / etc. were always known and never rewritten,
|
|
32
|
+
* so a `[[/section]]` in real data is a GENUINE wikilink and must be preserved.
|
|
33
|
+
*
|
|
34
|
+
* Genuine wikilinks are otherwise preserved too: `[[/foo/bar]]` (multi-segment),
|
|
35
|
+
* `[[/font|alias]]` (aliased), `[[/Font]]` (uppercase → case-sensitive page
|
|
36
|
+
* name), and `[[/wiki-page]]` (non-recoverable name) are all left untouched.
|
|
37
|
+
*
|
|
38
|
+
* ── Inherent ambiguity ───────────────────────────────────────────────
|
|
39
|
+
* `[[/font]]` could be a corrupted `</font>` OR a genuine wikilink to a real
|
|
40
|
+
* page literally at `/font`. They are indistinguishable from the text alone.
|
|
41
|
+
* We resolve this conservatively: a `[[/<x>]]` whose `/<x>` matches a **live
|
|
42
|
+
* content page** (published, not a redirect stub) is NOT reverted — it is
|
|
43
|
+
* reported by `detect` so an operator can decide manually. The revert therefore
|
|
44
|
+
* only touches occurrences that have no same-named live page to be mistaken for.
|
|
45
|
+
* Pages literally named after a deprecated tag (`/font`, `/center`, …) are very
|
|
46
|
+
* rare, but an absent-page `[[/font]]` is still reverted — see the docs Caution.
|
|
47
|
+
* ─────────────────────────────────────────────────────────────────────
|
|
48
|
+
*
|
|
49
|
+
* Like `wikilink-format`, every body rewrite routes through
|
|
50
|
+
* `ctx.rewritePageBody` (the `updatePage`-equivalent path) so `yjsState` /
|
|
51
|
+
* `yjsCheckpointAt` are nulled and an active editor's stale `Y.Doc` cannot
|
|
52
|
+
* silently revert the recovery (RFC-0008 §4.3.1).
|
|
53
|
+
*
|
|
54
|
+
* Idempotent: once reverted, `</x>` no longer matches this migration's
|
|
55
|
+
* detection regex (it scans for `[[/...]]`, not `</...>`), and a re-run of
|
|
56
|
+
* `wikilink-format` leaves `</x>` alone because `x` is now in
|
|
57
|
+
* `KNOWN_HTML_ELEMENTS`.
|
|
58
|
+
*/
|
|
59
|
+
/**
|
|
60
|
+
* The five deprecated/obsolete presentational tags absent from
|
|
61
|
+
* `KNOWN_HTML_ELEMENTS` when `wikilink-format` first ran — the ONLY close tags
|
|
62
|
+
* the misfire could have rewritten to `[[/x]]`. Recovery is scoped to exactly
|
|
63
|
+
* these so a genuine single-segment wikilink to any other element-named page
|
|
64
|
+
* (`[[/section]]`, `[[/div]]`, `[[/br]]`) is never destroyed.
|
|
65
|
+
*/
|
|
66
|
+
exports.RECOVERABLE_DEPRECATED_TAGS = new Set(['font', 'center', 'marquee', 'blink', 'applet']);
|
|
67
|
+
/**
|
|
68
|
+
* Matches a corrupted-wikilink candidate `[[/<segment>]]` with a single
|
|
69
|
+
* path segment and no alias. The capture group grabs the bare segment
|
|
70
|
+
* (`font` in `[[/font]]`). The `[^[\]|/]+` class excludes `[`, `]`, `|`, and
|
|
71
|
+
* `/`, so multi-segment (`[[/foo/bar]]`) and aliased (`[[/font|x]]`) forms
|
|
72
|
+
* never match here — only `shouldRecoverSegment` then filters by tag name.
|
|
73
|
+
*/
|
|
74
|
+
exports.WIKILINK_HTML_CANDIDATE_REGEX = /\[\[\/([^[\]|/]+)\]\]/g;
|
|
75
|
+
/**
|
|
76
|
+
* True iff `[[/<segment>]]` should be reverted to `</segment>`: the segment is
|
|
77
|
+
* a lowercase-ASCII identifier that is one of the FIVE deprecated tags the
|
|
78
|
+
* misfire could have produced. Uppercase (`/Font`), non-deprecated element
|
|
79
|
+
* names (`/section`, `/div`), and non-HTML names (`/wiki`) are genuine
|
|
80
|
+
* wikilinks and are left alone.
|
|
81
|
+
*/
|
|
82
|
+
function shouldRecoverSegment(segment) {
|
|
83
|
+
if (!/^[a-z][a-z0-9]*$/.test(segment))
|
|
84
|
+
return false;
|
|
85
|
+
return exports.RECOVERABLE_DEPRECATED_TAGS.has(segment);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Single-pass scan: locate every recoverable `[[/<deprecated-tag>]]` occurrence
|
|
89
|
+
* in `body`. Pure — no rewrite is applied here (the rewrite happens in
|
|
90
|
+
* `rewriteBody` after same-name page collisions have been resolved
|
|
91
|
+
* per-occurrence).
|
|
92
|
+
*/
|
|
93
|
+
function detectRecoverable(body) {
|
|
94
|
+
const occurrences = [];
|
|
95
|
+
exports.WIKILINK_HTML_CANDIDATE_REGEX.lastIndex = 0;
|
|
96
|
+
let match = exports.WIKILINK_HTML_CANDIDATE_REGEX.exec(body);
|
|
97
|
+
while (match !== null) {
|
|
98
|
+
const segment = match[1];
|
|
99
|
+
if (shouldRecoverSegment(segment)) {
|
|
100
|
+
occurrences.push({ raw: match[0], element: segment });
|
|
101
|
+
}
|
|
102
|
+
match = exports.WIKILINK_HTML_CANDIDATE_REGEX.exec(body);
|
|
103
|
+
}
|
|
104
|
+
return occurrences;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Rewrite `body`, reverting `[[/<x>]]` → `</x>` for every recoverable element.
|
|
108
|
+
* Elements in `skip` (those that collide with a live same-named page) are left
|
|
109
|
+
* untouched. Returns the input by reference when nothing changed so callers can
|
|
110
|
+
* cheap-skip.
|
|
111
|
+
*/
|
|
112
|
+
function rewriteBody(body, skip) {
|
|
113
|
+
let changed = false;
|
|
114
|
+
const rewritten = body.replace(exports.WIKILINK_HTML_CANDIDATE_REGEX, (whole, segment) => {
|
|
115
|
+
if (!shouldRecoverSegment(segment))
|
|
116
|
+
return whole;
|
|
117
|
+
if (skip.has(segment))
|
|
118
|
+
return whole;
|
|
119
|
+
changed = true;
|
|
120
|
+
return `</${segment}>`;
|
|
121
|
+
});
|
|
122
|
+
return changed ? rewritten : body;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* A memoised live-content `/<element>` existence probe. The probe restricts to
|
|
126
|
+
* a **published, non-redirect** page so a leftover redirect stub (deleting
|
|
127
|
+
* `/font` leaves a published `redirect /trash/font` at `/font`) does NOT shadow
|
|
128
|
+
* a genuinely corrupted `[[/font]]`. `{ redirectTo: null }` matches both a
|
|
129
|
+
* missing field and an explicit null. `Page.exists` results are cached per
|
|
130
|
+
* element so a widely-used corrupted tag costs one probe across the whole walk.
|
|
131
|
+
*
|
|
132
|
+
* The status filter mirrors the walk itself (`forEachPublishedCurrentRevision`
|
|
133
|
+
* + `Page.isPublished`): `status: published` OR legacy `status: null`. As a
|
|
134
|
+
* PREFLIGHT run against a raw v1 DB (before any v2 boot writes `status`),
|
|
135
|
+
* a genuine `/font` page still carries `status: null`; matching only
|
|
136
|
+
* `STATUS_PUBLISHED` would miss it and let a real collision's `[[/font]]` be
|
|
137
|
+
* destroyed. The looser `$or` keeps the collision-skip firing in that window.
|
|
138
|
+
*/
|
|
139
|
+
function makePageExistsProbe(Page) {
|
|
140
|
+
const cache = new Map();
|
|
141
|
+
return async (element) => {
|
|
142
|
+
const cached = cache.get(element);
|
|
143
|
+
if (cached !== undefined)
|
|
144
|
+
return cached;
|
|
145
|
+
const exists = Boolean(await Page.exists({ path: `/${element}`, redirectTo: null, $or: [{ status: page_1.STATUS_PUBLISHED }, { status: null }] }));
|
|
146
|
+
cache.set(element, exists);
|
|
147
|
+
return exists;
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Walk every published page's current revision body, detect corrupted
|
|
152
|
+
* `[[/<deprecated-tag>]]` occurrences, and for each candidate element check
|
|
153
|
+
* whether a live same-named page (`/<element>`) exists. Colliding elements are
|
|
154
|
+
* reported (not reverted); the rest are staged for rewrite.
|
|
155
|
+
*/
|
|
156
|
+
async function scan(ctx) {
|
|
157
|
+
const Page = ctx.crowi.model('Page');
|
|
158
|
+
const pageExists = makePageExistsProbe(Page);
|
|
159
|
+
const work = [];
|
|
160
|
+
const collidingElements = new Set();
|
|
161
|
+
const collisions = [];
|
|
162
|
+
let revertibleOccurrences = 0;
|
|
163
|
+
await (0, published_current_revision_1.forEachPublishedCurrentRevision)(ctx, { projection: 'body path' }, async ({ revision, pageId }) => {
|
|
164
|
+
const body = revision.body;
|
|
165
|
+
if (typeof body !== 'string' || !body.includes('[[/'))
|
|
166
|
+
return;
|
|
167
|
+
const pagePath = typeof revision.path === 'string' ? revision.path : undefined;
|
|
168
|
+
const occurrences = detectRecoverable(body);
|
|
169
|
+
if (occurrences.length === 0)
|
|
170
|
+
return;
|
|
171
|
+
// Partition this page's elements into collide-skip vs revertible. Each
|
|
172
|
+
// colliding element is recorded once per holding page so the report can
|
|
173
|
+
// name the page(s) an operator has to resolve by hand (a page may hold
|
|
174
|
+
// several colliding tags — dedupe within this page).
|
|
175
|
+
const skip = new Set();
|
|
176
|
+
let pageReverted = 0;
|
|
177
|
+
for (const occ of occurrences) {
|
|
178
|
+
if (await pageExists(occ.element)) {
|
|
179
|
+
if (!skip.has(occ.element))
|
|
180
|
+
collisions.push({ element: occ.element, pageId, pagePath });
|
|
181
|
+
skip.add(occ.element);
|
|
182
|
+
collidingElements.add(occ.element);
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
pageReverted += 1;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (pageReverted === 0)
|
|
189
|
+
return;
|
|
190
|
+
const newBody = rewriteBody(body, skip);
|
|
191
|
+
work.push({ pageId, newBody });
|
|
192
|
+
revertibleOccurrences += pageReverted;
|
|
193
|
+
});
|
|
194
|
+
return { work, revertibleOccurrences, collidingElements, collisions };
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Render collision records into an operator-actionable string that names the
|
|
198
|
+
* holding page(s) per element, e.g.
|
|
199
|
+
* `/font (in /docs/setup, /guide); /center (in /notes)`. The element→pages
|
|
200
|
+
* mapping is preserved so the operator knows exactly which pages to open from
|
|
201
|
+
* the `migrate plan` output / boot warn log. Elements are sorted; per-element
|
|
202
|
+
* pages prefer the page path, falling back to the page id when the revision
|
|
203
|
+
* carried no path.
|
|
204
|
+
*/
|
|
205
|
+
function formatCollisions(collisions) {
|
|
206
|
+
const byElement = new Map();
|
|
207
|
+
for (const c of collisions) {
|
|
208
|
+
const label = c.pagePath ?? c.pageId;
|
|
209
|
+
const list = byElement.get(c.element);
|
|
210
|
+
if (list) {
|
|
211
|
+
if (!list.includes(label))
|
|
212
|
+
list.push(label);
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
byElement.set(c.element, [label]);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return [...byElement.entries()]
|
|
219
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
220
|
+
.map(([element, pages]) => `/${element} (in ${pages.join(', ')})`)
|
|
221
|
+
.join('; ');
|
|
222
|
+
}
|
|
223
|
+
exports.wikilinkHtmlRecover = (0, types_1.defineMigration)({
|
|
224
|
+
id: 'wikilink-html-recover',
|
|
225
|
+
fromVersion: '2.1',
|
|
226
|
+
toVersion: '2.1',
|
|
227
|
+
layer: 'preflight',
|
|
228
|
+
// `fromVersion: '2.1'` already sequences this after `wikilink-format`
|
|
229
|
+
// (`fromVersion: '1.x'`) — the registry orders by `fromVersion` FIRST
|
|
230
|
+
// (registry.ts compareMigrations), so the misfire's source is registered
|
|
231
|
+
// before this recovery regardless of `order`. No other `2.1` migration
|
|
232
|
+
// exists today, so `order` is cosmetic here.
|
|
233
|
+
order: 100,
|
|
234
|
+
description: 'Recover deprecated HTML close tags (</font> etc.) corrupted to wikilinks by the wikilink-format misfire',
|
|
235
|
+
/**
|
|
236
|
+
* Pending iff at least one published page's current revision body still
|
|
237
|
+
* carries a revertible `[[/<deprecated-tag>]]` whose element has no live
|
|
238
|
+
* same-named page. There is no index on `revision.body`, so this walks
|
|
239
|
+
* published pages (projecting `body`) and short-circuits at the first
|
|
240
|
+
* revertible occurrence.
|
|
241
|
+
*
|
|
242
|
+
* Colliding occurrences (`[[/font]]` with a live `/font` page) do NOT count
|
|
243
|
+
* as pending: this migration will never revert them, so reporting pending
|
|
244
|
+
* for them would block boot forever under preflight + `block`.
|
|
245
|
+
*/
|
|
246
|
+
isPending: async (ctx) => {
|
|
247
|
+
const Page = ctx.crowi.model('Page');
|
|
248
|
+
const pageExists = makePageExistsProbe(Page);
|
|
249
|
+
let pending = false;
|
|
250
|
+
await (0, published_current_revision_1.forEachPublishedCurrentRevision)(ctx, { projection: 'body' }, async ({ revision }) => {
|
|
251
|
+
const body = revision.body;
|
|
252
|
+
if (typeof body !== 'string' || !body.includes('[[/'))
|
|
253
|
+
return;
|
|
254
|
+
for (const occ of detectRecoverable(body)) {
|
|
255
|
+
if (!(await pageExists(occ.element))) {
|
|
256
|
+
pending = true;
|
|
257
|
+
return published_current_revision_1.STOP;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
return pending;
|
|
262
|
+
},
|
|
263
|
+
/**
|
|
264
|
+
* Full scan for `plan`: report how many pages / occurrences would be
|
|
265
|
+
* reverted plus, separately, the deprecated-tag names that were left alone
|
|
266
|
+
* because a live same-named page exists (the operator must resolve those
|
|
267
|
+
* by hand). Not called at boot.
|
|
268
|
+
*/
|
|
269
|
+
detect: async (ctx) => {
|
|
270
|
+
const { work, revertibleOccurrences, collidingElements, collisions } = await scan(ctx);
|
|
271
|
+
const colliding = [...collidingElements].sort();
|
|
272
|
+
const collisionNote = colliding.length > 0 ? `; ${colliding.length} element(s) skipped due to same-named pages: ${formatCollisions(collisions)}` : '';
|
|
273
|
+
return {
|
|
274
|
+
summary: `${work.length} page(s) hold ${revertibleOccurrences} recoverable HTML close tag(s)${collisionNote}`,
|
|
275
|
+
counts: {
|
|
276
|
+
pages: work.length,
|
|
277
|
+
occurrences: revertibleOccurrences,
|
|
278
|
+
collisions: colliding.length,
|
|
279
|
+
},
|
|
280
|
+
};
|
|
281
|
+
},
|
|
282
|
+
stages: [
|
|
283
|
+
{
|
|
284
|
+
name: 'recover-html-close-tags',
|
|
285
|
+
fn: async (ctx) => {
|
|
286
|
+
if (ctx.dryRun) {
|
|
287
|
+
const { work, revertibleOccurrences, collidingElements } = await scan(ctx);
|
|
288
|
+
return {
|
|
289
|
+
name: 'recover-html-close-tags',
|
|
290
|
+
transformed: 0,
|
|
291
|
+
stats: { wouldRevert: work.length, occurrences: revertibleOccurrences, collisions: collidingElements.size },
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
const actingUserId = await (0, helpers_1.resolveActingUserId)(ctx, 'wikilink-html-recover');
|
|
295
|
+
const { work, collidingElements, collisions } = await scan(ctx);
|
|
296
|
+
ctx.progress.setTotal(work.length);
|
|
297
|
+
let reverted = 0;
|
|
298
|
+
for (const page of work) {
|
|
299
|
+
await ctx.rewritePageBody(page.pageId, page.newBody, { userId: actingUserId });
|
|
300
|
+
reverted += 1;
|
|
301
|
+
ctx.progress.increment();
|
|
302
|
+
}
|
|
303
|
+
if (reverted > 0) {
|
|
304
|
+
ctx.logger.info(`wikilink-html-recover: reverted HTML close tags on ${reverted} page(s) via the updatePage path (yjsState invalidated)`);
|
|
305
|
+
}
|
|
306
|
+
if (collidingElements.size > 0) {
|
|
307
|
+
ctx.logger.warn(`wikilink-html-recover: left ${collidingElements.size} element(s) untouched because a same-named page exists: ${formatCollisions(collisions)} — open these pages and resolve them manually`);
|
|
308
|
+
}
|
|
309
|
+
return { name: 'recover-html-close-tags', transformed: reverted, stats: { collisions: collidingElements.size } };
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
],
|
|
313
|
+
});
|
|
314
|
+
//# sourceMappingURL=wikilink-html-recover.js.map
|