diff --git a/docs/specs/ops.yml b/docs/specs/ops.yml index 130a2aac359..540d1893c33 100644 --- a/docs/specs/ops.yml +++ b/docs/specs/ops.yml @@ -191,7 +191,7 @@ outputs: "files": [ { "url": "/admin/integrate-with-microsoft-teams", - "redirect_url": "basics/teams-integration", + "redirect_url": "/admin/basics/teams-integration", "document_id": "b1c6c9d3-40a8-a21d-98e8-a3cbf54eaeb4", "document_version_independent_id": "b1c6c9d3-40a8-a21d-98e8-a3cbf54eaeb4", "canonical_url": "https://docs.com/en-us/admin/integrate-with-microsoft-teams" diff --git a/docs/specs/redirection.yml b/docs/specs/redirection.yml index 36fb1a727c3..7eee501dd05 100644 --- a/docs/specs/redirection.yml +++ b/docs/specs/redirection.yml @@ -976,3 +976,180 @@ outputs: .errors.log: | {"message_severity":"warning","code":"path-invalid","message":"Path /*invalid.md contains invalid chars '<', '>', '*'."} {"message_severity":"warning","code":"missing-attribute","message":"Missing required attribute: '(source_path or source_path_from_root) or redirect_url'."} +--- +# Remove redirect_url hostname when it is the same as hostname or alternativeHostName in despite of redirect_document_id +repos: + https://docs.com/ops/redirect: + - files: + redirections.json: | + { + "redirections": [ + { + "source_path": "original.md", + "redirect_url": "https://docs.com/folder/a", + "redirect_document_id": "true" + }, + { + "source_path": "original2.md", + "redirect_url": "https://docs.com/folder/b", + "redirect_document_id": "false" + }, + { + "source_path": "original3.md", + "redirect_url": "https://new-docs.com/folder/c", + "redirect_document_id": "true" + }, + { + "source_path": "original4.md", + "redirect_url": "https://new-docs.com/folder/d", + "redirect_document_id": "false" + }, + { + "source_path": "original5.md", + "redirect_url": "https://docs-diff.com/folder/c", + "redirect_document_id": "true" + }, + { + "source_path": "original6.md", + "redirect_url": "https://docs-diff.com/folder/d", + "redirect_document_id": "false" + }, + ] + } + docfx.yml: | + hostname: docs.com + alternativeHostName: new-docs.com + name: docset + product: product + folder/index.md: +outputs: + folder/index.json: + .publish.json: | + { + "name": "docset", + "product": "product", + "base_path": "/", + "files": [ + { + "url": "/original", + "redirect_url": "/folder/a", + "document_id": "6172869a-1d42-80e4-5d0c-707167a0d4c1", + "document_version_independent_id": "6172869a-1d42-80e4-5d0c-707167a0d4c1", + "canonical_url": "https://docs.com/en-us/original" + }, + { + "url": "/original2", + "redirect_url": "/folder/b", + "document_id": "0e929cdb-46ae-915a-031f-4c6f8e8f6a1a", + "document_version_independent_id": "0e929cdb-46ae-915a-031f-4c6f8e8f6a1a", + "canonical_url": "https://docs.com/en-us/original2" + }, + { + "url": "/original3", + "redirect_url": "/folder/c", + "document_id": "01bf1826-aa28-49c6-d258-4c3837762c95", + "document_version_independent_id": "01bf1826-aa28-49c6-d258-4c3837762c95", + "canonical_url": "https://docs.com/en-us/original3" + }, + { + "url": "/original4", + "redirect_url": "/folder/d", + "document_id": "168b8137-5da2-ede9-224a-b295bb82ee6a", + "document_version_independent_id": "168b8137-5da2-ede9-224a-b295bb82ee6a", + "canonical_url": "https://docs.com/en-us/original4" + }, + { + "url": "/original5", + "redirect_url": "https://docs-diff.com/folder/c", + "document_id": "5269a2f9-8e29-8fed-7da3-4b08cbcb5972", + "document_version_independent_id": "5269a2f9-8e29-8fed-7da3-4b08cbcb5972", + "canonical_url": "https://docs.com/en-us/original5" + }, + { + "url": "/original6", + "redirect_url": "https://docs-diff.com/folder/d", + "document_id": "3c570421-59fc-1dc7-d86a-43dbdf5d391b", + "document_version_independent_id": "3c570421-59fc-1dc7-d86a-43dbdf5d391b", + "canonical_url": "https://docs.com/en-us/original6" + }, + { + "url": "/folder/", + "path": "folder/index.json", + "source_path": "folder/index.md", + "canonical_url": "https://docs.com/en-us/folder/", + "document_id": "87407f22-7c8e-317e-430d-96980c2fd1a6", + "document_version_independent_id": "87407f22-7c8e-317e-430d-96980c2fd1a6", + "site_name": "Docs", + "depot_name": "product.docset", + } + ] + } + .errors.log: | + {"message_severity":"suggestion","code":"redirect-url-invalid","message":"Can't redirect document ID for redirected file 'original.md' because redirect URL 'https://docs.com/folder/a' is invalid or is in a different docset. Specify a redirect_url in the same docset, or set redirect_document_id to false in .openpublishing.redirection.json.","file":"redirections.json"} + {"message_severity":"suggestion","code":"redirect-url-invalid","message":"Can't redirect document ID for redirected file 'original3.md' because redirect URL 'https://new-docs.com/folder/c' is invalid or is in a different docset. Specify a redirect_url in the same docset, or set redirect_document_id to false in .openpublishing.redirection.json.","file":"redirections.json"} + {"message_severity":"suggestion","code":"redirect-url-invalid","message":"Can't redirect document ID for redirected file 'original5.md' because redirect URL 'https://docs-diff.com/folder/c' is invalid or is in a different docset. Specify a redirect_url in the same docset, or set redirect_document_id to false in .openpublishing.redirection.json.","file":"redirections.json"} +--- +# convert relative redirect url to absolute path in despite of redirect_document_id config +repos: + https://docs.com/ops/redirect: + - files: + redirections.json: | + { + "redirections": [ + { + "source_path": "original.md", + "redirect_url": "folder/a", + "redirect_document_id": "true" + }, + { + "source_path": "original2.md", + "redirect_url": "folder/b", + "redirect_document_id": "false" + } + ] + } + docfx.yml: | + hostname: docs.com + name: docset + product: product + folder/index.md: +outputs: + folder/index.json: + .publish.json: | + { + "name": "docset", + "product": "product", + "base_path": "/", + "files": [ + { + "url": "/original", + "locale": "en-us", + "redirect_url": "/folder/a", + "document_id": "6172869a-1d42-80e4-5d0c-707167a0d4c1", + "document_version_independent_id": "6172869a-1d42-80e4-5d0c-707167a0d4c1", + "canonical_url": "https://docs.com/en-us/original" + }, + { + "url": "/original2", + "locale": "en-us", + "redirect_url": "/folder/b", + "document_id": "0e929cdb-46ae-915a-031f-4c6f8e8f6a1a", + "document_version_independent_id": "0e929cdb-46ae-915a-031f-4c6f8e8f6a1a", + "canonical_url": "https://docs.com/en-us/original2" + }, + { + "url": "/folder/", + "path": "folder/index.json", + "source_path": "folder/index.md", + "locale": "en-us", + "canonical_url": "https://docs.com/en-us/folder/", + "document_id": "87407f22-7c8e-317e-430d-96980c2fd1a6", + "document_version_independent_id": "87407f22-7c8e-317e-430d-96980c2fd1a6", + "site_name": "Docs", + "depot_name": "product.docset", + } + ] + } + .errors.log: | + {"message_severity":"suggestion","code":"redirect-url-invalid","message":"Can't redirect document ID for redirected file 'original.md' because redirect URL 'folder/a' is invalid or is in a different docset. Specify a redirect_url in the same docset, or set redirect_document_id to false in .openpublishing.redirection.json.","file":"redirections.json"} +--- diff --git a/src/docfx/build/redirection/RedirectionProvider.cs b/src/docfx/build/redirection/RedirectionProvider.cs index 877acfc19a2..15cd85a786e 100644 --- a/src/docfx/build/redirection/RedirectionProvider.cs +++ b/src/docfx/build/redirection/RedirectionProvider.cs @@ -95,14 +95,14 @@ public FilePath GetOriginalFile(FilePath file) using (Progress.Start("Loading redirections")) { var redirections = LoadRedirectionModel(); - var redirectUrls = GetRedirectUrls(redirections, _config.HostName); + var redirectUrls = GetRedirectUrls(redirections); var redirectPaths = redirectUrls.Keys.Select(x => x.Path).ToHashSet(); return (redirectUrls, redirectPaths, redirections); } } - private Dictionary GetRedirectUrls(RedirectionItem[] redirections, string hostName) + private Dictionary GetRedirectUrls(RedirectionItem[] redirections) { var redirectUrls = new Dictionary(); @@ -127,23 +127,21 @@ private Dictionary GetRedirectUrls(RedirectionItem[] redirecti var monikers = item.Monikers is null ? default : _monikerProvider.Validate(_errors, item.Monikers); var filePath = FilePath.Redirection(path, monikers); - if (item.RedirectDocumentId) + switch (UrlUtility.GetLinkType(absoluteRedirectUrl)) { - switch (UrlUtility.GetLinkType(absoluteRedirectUrl)) - { - case LinkType.RelativePath: - var siteUrl = _documentProvider.GetSiteUrl(filePath); - absoluteRedirectUrl = PathUtility.Normalize(Path.Combine(Path.GetDirectoryName(siteUrl) ?? "", absoluteRedirectUrl)); - break; - case LinkType.AbsolutePath: - break; - case LinkType.External: - absoluteRedirectUrl = UrlUtility.RemoveLeadingHostName(absoluteRedirectUrl, hostName, removeLocale: true); - break; - default: - _errors.Add(Errors.Redirection.RedirectUrlInvalid(path, redirectUrl)); - break; - } + case LinkType.RelativePath: + var siteUrl = _documentProvider.GetSiteUrl(filePath); + absoluteRedirectUrl = PathUtility.Normalize(Path.Combine(Path.GetDirectoryName(siteUrl) ?? "", absoluteRedirectUrl)); + break; + case LinkType.AbsolutePath: + break; + case LinkType.External: + absoluteRedirectUrl = UrlUtility.RemoveLeadingHostName(absoluteRedirectUrl, _config.HostName, removeLocale: true); + absoluteRedirectUrl = UrlUtility.RemoveLeadingHostName(absoluteRedirectUrl, _config.AlternativeHostName, removeLocale: true); + break; + default: + _errors.Add(Errors.Redirection.RedirectUrlInvalid(path, redirectUrl)); + break; } if (!redirectUrls.TryAdd(filePath, absoluteRedirectUrl))