Link Cartfile dependencies in the source viewer
What does this MR do and why?
A Cartfile is highlighted by the backend today. cartfile is listed in LEGACY_FILE_TYPES, so the file is served through the legacy viewer, where the server-side DependencyLinker runs. The origins are linked on master; nothing is broken.
This MR moves the file type over to the frontend source viewer without losing those links. It adds a Highlight.js dependency linker for cartfile, registers it in link_dependencies.js alongside the existing gemfile, podspec_json, composer_json and go_sum linkers, and removes cartfile from LEGACY_FILE_TYPES, the same way !255262 (merged) does for podfile.
It handles the two origin shapes Carthage supports:
github "Owner/Repo"links theOwner/Repotext tohttps://github.com/Owner/Repo.git "https://...",binary "https://..."and the URL form ofgithub "https://..."(GitHub Enterprise) link the URL to itself.
Both patterns follow what the Ruby linker accepts rather than the shape of a tidy file. MethodLinker#method_call_regex allows leading whitespace and any run of whitespace between the keyword and the quoted value, so an indented entry and a column-aligned one are matched here too, and the original spacing is preserved in the output.
The URL match runs to the closing quote rather than stopping at an ampersand, so a query string stays whole. The URL is unescaped before the link is built, because createLink escapes what it is given.
Both patterns are anchored to the start of a line and require one of the three keywords, so a commented-out line such as # github "Owner/Repo" or an unrecognised keyword is left untouched. Version constraints after the origin (>= 2.3.1, ~> 1.0) are not part of the match.
A Cartfile is highlighted as plaintext, so the whole line arrives as a single <span class="">...</span> with the quotes already escaped as " and ampersands as &; the regexes are written against that exact shape.
References
- Resolves #367651
- Sibling changes for the other Cocoa manifests: !255262 (merged) (Podfile) and !255264 (merged) (podspec)
- Other file types moving to the new viewer: !255267 (merged) (requirements.txt) and !255271 (merged) (go.mod)
- Reuses
createLinkfromapp/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/dependency_linker_util.js, so links carry the sametargetandrelattributes as every other linker.unescapecomes fromlodash-es, as it does inpackage_json_linker.js. - Each of those merge requests removes an entry from
LEGACY_FILE_TYPES, and removing enough entries brings the array under the line limit so Prettier collapses it. Expect a one-line conflict on each merge after the first.
Differences
Before: A Cartfile was rendered by the legacy backend viewer, with links produced by Gitlab::DependencyLinker::CartfileLinker.
After: A Cartfile is rendered by the frontend source viewer, with the same links produced client side. ReactiveCocoa/ReactiveCocoa links to https://github.com/ReactiveCocoa/ReactiveCocoa, opening in a new tab. The git, binary and URL-style github origins are clickable links to their URL, query string included. Indented and column-aligned entries are linked and keep their spacing. Commented-out lines, unknown keywords and version constraints are unchanged.
How to set up and validate locally
- In a project, add a file named
Cartfilewith the following content:
github "ReactiveCocoa/ReactiveCocoa" >= 2.3.1
github "Mantle/Mantle" ~> 1.0
github "Indented/Repo"
github "Aligned/Repo"
github "https://enterprise.local/project/repo"
git "https://enterprise.local/desktop/git-error-translations2.git"
binary "https://my.domain.com/release/MyFramework.json" ~> 2.3
binary "https://my.domain.com/release/MyFramework.json?arch=arm64&variant=debug"
# github "Commented/Out"
local "Unknown/Keyword"- Open the file in the repository view.
ReactiveCocoa/ReactiveCocoa,Mantle/Mantle,Indented/RepoandAligned/Reposhould link to their GitHub repositories, with the indentation and the extra spaces intact. All four URLs should link to themselves, and the last one should include&variant=debugin both the link text and its target rather than stopping at?arch=arm64. The commented line and the unknown keyword should not be links.
Specs:
yarn jest spec/frontend/vue_shared/components/source_viewer/plugins/utils/cartfile_linker_spec.js spec/frontend/vue_shared/components/source_viewer/plugins/link_dependencies_spec.js spec/frontend/repository/components/blob_content_viewer_spec.jscartfile_linker_spec.js covers GitHub shorthand origins with version constraints, all three URL-origin keywords, indented and column-aligned origins, a URL with an escaped query string, and that comments and unknown keywords are untouched. link_dependencies_spec.js asserts the cartfile file type is routed to the new linker. blob_content_viewer_spec.js covers the LEGACY_FILE_TYPES change.
MR acceptance checklist
- The change is limited to the frontend source viewer; no backend, database, or API changes.
-
cartfileis removed fromLEGACY_FILE_TYPES, so the file is actually served by the frontend viewer and the new linker is reached. - Links are built with the shared
createLinkhelper, so they carrytarget="_blank"andrel="nofollow noreferrer noopener"like every other dependency linker. - Only
github,gitandbinaryorigins are linked; comments, unknown keywords and version constraints are not rewritten. - Leading and intra-line whitespace is matched the way
MethodLinker#method_call_regexmatches it, and preserved in the output. - A URL keeps its full query string, and is unescaped before the link is built so an escaped separator does not come back double-escaped.
- Unit specs added for the linker and for its registration in
link_dependencies.js; the source viewer plugin suite and the blob content viewer suite pass locally. -
Changelog: changedtrailer is on the commit, since this moves an existing behaviour to the frontend viewer rather than adding a new one. - No documentation change required; the links a reader sees are unchanged.
- No feature flag needed; the change is small and isolated to one file type.