Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

gleam / compiler-core / src / docs / source_links.rs
4.1 kB 125 lines
1// SPDX-License-Identifier: Apache-2.0 2// SPDX-FileCopyrightText: 2020 The Gleam contributors 3 4use crate::{ 5 ast::SrcSpan, 6 build, 7 config::{PackageConfig, Repository}, 8 line_numbers::LineNumbers, 9 paths::ProjectPaths, 10}; 11 12use camino::{Utf8Component, Utf8Path, Utf8PathBuf}; 13 14pub struct SourceLinker { 15 line_numbers: LineNumbers, 16 url_pattern: Option<(String, String)>, 17} 18 19impl SourceLinker { 20 pub fn new( 21 paths: &ProjectPaths, 22 project_config: &PackageConfig, 23 module: &build::Module, 24 ) -> Self { 25 let path = paths 26 .src_directory() 27 .join(module.name.as_str()) 28 .strip_prefix(paths.root()) 29 .expect("path is not in root") 30 .with_extension("gleam"); 31 32 let path_in_repo = match project_config 33 .repository 34 .as_ref() 35 .map(|r| r.path()) 36 .unwrap_or_default() 37 { 38 Some(repo_path) => to_url_path(&Utf8PathBuf::from(repo_path).join(path)), 39 _ => to_url_path(&path), 40 } 41 .unwrap_or_default(); 42 43 let tag = project_config.tag_for_version(&project_config.version); 44 45 let url_pattern = project_config 46 .repository 47 .as_ref() 48 .map(|r| match r { 49 Repository::GitHub { user, repo, .. } => Some(( 50 format!("https://github.com/{user}/{repo}/blob/{tag}/{path_in_repo}#L"), 51 "-L".into(), 52 )), 53 Repository::GitLab { user, repo, .. } => Some(( 54 format!("https://gitlab.com/{user}/{repo}/-/blob/{tag}/{path_in_repo}#L"), 55 "-".into(), 56 )), 57 Repository::BitBucket { user, repo, .. } => Some(( 58 format!("https://bitbucket.com/{user}/{repo}/src/{tag}/{path_in_repo}#lines-"), 59 ":".into(), 60 )), 61 Repository::Codeberg { user, repo, .. } => Some(( 62 format!("https://codeberg.org/{user}/{repo}/src/tag/{tag}/{path_in_repo}#L"), 63 "-".into(), 64 )), 65 Repository::SourceHut { user, repo, .. } => Some(( 66 format!("https://git.sr.ht/~{user}/{repo}/tree/{tag}/item/{path_in_repo}#L"), 67 "-".into(), 68 )), 69 Repository::Tangled { user, repo, .. } => Some(( 70 format!("https://tangled.sh/{user}/{repo}/tree/{tag}/{path_in_repo}#L"), 71 "-".into(), 72 )), 73 Repository::Gitea { 74 user, repo, host, .. 75 } 76 | Repository::Forgejo { 77 user, repo, host, .. 78 } => { 79 let string_host = host.to_string(); 80 let cleaned_host = string_host.trim_end_matches('/'); 81 Some(( 82 format!("{cleaned_host}/{user}/{repo}/src/tag/{tag}/{path_in_repo}#L",), 83 "-L".into(), 84 )) 85 } 86 Repository::Custom { .. } => None, 87 }) 88 .unwrap_or_default(); 89 90 SourceLinker { 91 line_numbers: LineNumbers::new(&module.code), 92 url_pattern, 93 } 94 } 95 96 pub fn url(&self, span: SrcSpan) -> String { 97 match &self.url_pattern { 98 Some((base, line_sep)) => { 99 let start_line = self.line_numbers.line_number(span.start); 100 let end_line = self.line_numbers.line_number(span.end); 101 if start_line == end_line { 102 format!("{base}{start_line}") 103 } else { 104 format!("{base}{start_line}{line_sep}{end_line}") 105 } 106 } 107 108 None => "".into(), 109 } 110 } 111} 112 113fn to_url_path(path: &Utf8Path) -> Option<String> { 114 let mut buf = String::new(); 115 for c in path.components() { 116 if let Utf8Component::Normal(s) = c { 117 buf.push_str(s); 118 } 119 buf.push('/'); 120 } 121 122 let _ = buf.pop(); 123 124 Some(buf) 125}