Skip to content

Commit

Permalink
Copy citation file content, in APA and BibTex format, on repo home pa…
Browse files Browse the repository at this point in the history
…ge (#19999)

Add feature to easily copy CITATION.cff content in APA and BibTex format.
  • Loading branch information
sarrooo authored Nov 11, 2022
1 parent 9db2217 commit 9f8e778
Show file tree
Hide file tree
Showing 10 changed files with 474 additions and 21 deletions.
2 changes: 2 additions & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -1013,10 +1013,12 @@ unstar = Unstar
star = Star
fork = Fork
download_archive = Download Repository
more_actions = More Actions

no_desc = No Description
quick_guide = Quick Guide
clone_this_repo = Clone this repository
cite_this_repo = Cite this repository
create_new_repo_command = Creating a new repository on the command line
push_exist_repo = Pushing an existing repository from the command line
empty_message = This repository does not contain any content.
Expand Down
289 changes: 271 additions & 18 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
"node": ">= 14.0.0"
},
"dependencies": {
"@citation-js/core": "0.6.1",
"@citation-js/plugin-bibtex": "0.6.1",
"@citation-js/plugin-csl": "0.6.3",
"@citation-js/plugin-software-formats": "0.6.0",
"@claviska/jquery-minicolors": "2.3.6",
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
"@primer/octicons": "17.7.0",
Expand Down
45 changes: 45 additions & 0 deletions routers/web/repo/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -730,6 +730,44 @@ func checkHomeCodeViewable(ctx *context.Context) {
ctx.NotFound("Home", fmt.Errorf(ctx.Tr("units.error.no_unit_allowed_repo")))
}

func checkCitationFile(ctx *context.Context, entry *git.TreeEntry) {
if entry.Name() != "" {
return
}
tree, err := ctx.Repo.Commit.SubTree(ctx.Repo.TreePath)
if err != nil {
ctx.NotFoundOrServerError("Repo.Commit.SubTree", git.IsErrNotExist, err)
return
}
allEntries, err := tree.ListEntries()
if err != nil {
ctx.ServerError("ListEntries", err)
return
}
for _, entry := range allEntries {
if entry.Name() == "CITATION.cff" || entry.Name() == "CITATION.bib" {
ctx.Data["CitiationExist"] = true
// Read Citation file contents
blob := entry.Blob()
dataRc, err := blob.DataAsync()
if err != nil {
ctx.ServerError("DataAsync", err)
return
}
defer dataRc.Close()
buf := make([]byte, 1024)
n, err := util.ReadAtMost(dataRc, buf)
if err != nil {
ctx.ServerError("ReadAtMost", err)
return
}
buf = buf[:n]
ctx.PageData["citationFileContent"] = string(buf)
break
}
}
}

// Home render repository home page
func Home(ctx *context.Context) {
isFeed, _, showFeedType := feed.GetFeedType(ctx.Params(":reponame"), ctx.Req)
Expand Down Expand Up @@ -954,6 +992,13 @@ func renderCode(ctx *context.Context) {
return
}

if !ctx.Repo.Repository.IsEmpty {
checkCitationFile(ctx, entry)
if ctx.Written() {
return
}
}

renderLanguageStats(ctx)
if ctx.Written() {
return
Expand Down
11 changes: 11 additions & 0 deletions templates/repo/cite/cite_buttons.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<button class="ui basic citation button" id="citation-copy-apa" data-text="">
APA
</button>
<button class="ui basic citation button" id="citation-copy-bibtex" data-text="">
BibTeX
</button>
<!-- the value will be updated by initCitationFileCopyContent, the code below is used to avoid UI flicking -->
<input id="citation-copy-content" value="" size="1" readonly>
<button class="ui basic icon button tooltip" id="citation-clipboard-btn" data-content="{{.locale.Tr "copy"}}" data-clipboard-text="" data-clipboard-target="#citation-copy-content">
{{svg "octicon-copy"}}
</button>
22 changes: 22 additions & 0 deletions templates/repo/cite/cite_modal.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<div class="ui tiny modal" id="cite-repo-modal">
<div class="header">
{{.locale.Tr "repo.cite_this_repo"}}
</div>
<div class="content">
<div class="ui stackable secondary menu mobile--margin-between-items mobile--no-negative-margins no-vertical-tabs">
<div class="fitted item">
<div class="ui action input" id="citation-panel">
{{template "repo/cite/cite_buttons" .}}
<a id="goto-citation-btn" class="ui basic jump icon button tooltip" href="{{$.RepoLink}}/src/{{$.BranchName}}/CITATION.cff" data-position="top right" data-content="{{.locale.Tr "repo.find_file.go_to_file"}}">
{{svg "octicon-file-moved"}}
</a>
</div>
</div>
</div>
</div>
<div class="actions">
<div class="ui black deny button">
{{.locale.Tr "cancel"}}
</div>
</div>
</div>
8 changes: 6 additions & 2 deletions templates/repo/home.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -117,19 +117,23 @@
{{if eq $n 0}}
<div class="ui action tiny input" id="clone-panel">
{{template "repo/clone_buttons" .}}
<button id="download-btn" class="ui basic small compact jump dropdown icon button tooltip" data-content="{{.locale.Tr "repo.download_archive"}}" data-position="top right">
{{svg "octicon-download"}}
<button id="more-btn" class="ui basic small compact jump dropdown icon button tooltip" data-content="{{.locale.Tr "repo.more_actions"}}" data-position="top right">
{{svg "octicon-kebab-horizontal"}}
<div class="menu">
{{if not $.DisableDownloadSourceArchives}}
<a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefName}}.zip" rel="nofollow">{{svg "octicon-file-zip" 16 "mr-3"}}{{.locale.Tr "repo.download_zip"}}</a>
<a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefName}}.tar.gz" rel="nofollow">{{svg "octicon-file-zip" 16 "mr-3"}}{{.locale.Tr "repo.download_tar"}}</a>
<a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefName}}.bundle" rel="nofollow">{{svg "octicon-package" 16 "mr-3"}}{{.locale.Tr "repo.download_bundle"}}</a>
{{if .CitiationExist}}
<a class="item" id="cite-repo-button">{{svg "octicon-cross-reference" 16 "mr-3"}}{{.locale.Tr "repo.cite_this_repo"}}</a>
{{end}}
{{end}}
<a class="item js-clone-url-vsc" href="vscode://vscode.git/clone?url={{.CloneButtonOriginLink.HTTPS}}">{{svg "gitea-vscode" 16 "mr-3"}}{{.locale.Tr "repo.clone_in_vsc"}}</a>
</div>
</button>
{{template "repo/clone_script" .}}{{/* the script will update `.js-clone-url` and related elements */}}
</div>
{{template "repo/cite/cite_modal" .}}
{{end}}
{{if and (ne $n 0) (not .IsViewFile) (not .IsBlame)}}
<a class="ui button" href="{{.RepoLink}}/commits/{{.BranchNameSubURL}}/{{.TreePath | PathEscapeSegments}}">
Expand Down
60 changes: 60 additions & 0 deletions web_src/js/features/citation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import $ from 'jquery';

const {pageData} = window.config;

const initInputCitationValue = async ($citationCopyBibtex, $citationCopyApa) => {
const [{Cite, plugins}] = await Promise.all([
import(/* webpackChunkName: "citation-js-core" */'@citation-js/core'),
import(/* webpackChunkName: "citation-js-formats" */'@citation-js/plugin-software-formats'),
import(/* webpackChunkName: "citation-js-bibtex" */'@citation-js/plugin-bibtex'),
import(/* webpackChunkName: "citation-js-bibtex" */'@citation-js/plugin-csl'),
]);
const {citationFileContent} = pageData;
const config = plugins.config.get('@bibtex');
config.constants.fieldTypes.doi = ['field', 'literal'];
config.constants.fieldTypes.version = ['field', 'literal'];
const citationFormatter = new Cite(citationFileContent);
const lang = document.documentElement.lang || 'en-US';
const apaOutput = citationFormatter.format('bibliography', {template: 'apa', lang});
const bibtexOutput = citationFormatter.format('bibtex', {lang});
$citationCopyBibtex.attr('data-text', bibtexOutput);
$citationCopyApa.attr('data-text', apaOutput);
};

export function initCitationFileCopyContent() {
const defaultCitationFormat = 'apa'; // apa or bibtex

if (!pageData.citationFileContent) return;

const $citationCopyApa = $('#citation-copy-apa');
const $citationCopyBibtex = $('#citation-copy-bibtex');
const $inputContent = $('#citation-copy-content');

if ((!$citationCopyApa.length && !$citationCopyBibtex.length) || !$inputContent.length) return;
const updateUi = () => {
const isBibtex = (localStorage.getItem('citation-copy-format') || defaultCitationFormat) === 'bibtex';
const copyContent = (isBibtex ? $citationCopyBibtex : $citationCopyApa).attr('data-text');

$inputContent.val(copyContent);
$citationCopyBibtex.toggleClass('primary', isBibtex);
$citationCopyApa.toggleClass('primary', !isBibtex);
};
initInputCitationValue($citationCopyApa, $citationCopyBibtex).then(updateUi);

$citationCopyApa.on('click', () => {
localStorage.setItem('citation-copy-format', 'apa');
updateUi();
});
$citationCopyBibtex.on('click', () => {
localStorage.setItem('citation-copy-format', 'bibtex');
updateUi();
});

$inputContent.on('click', () => {
$inputContent.select();
});

$('#cite-repo-button').on('click', () => {
$('#cite-repo-modal').modal('show');
});
}
2 changes: 2 additions & 0 deletions web_src/js/features/repo-legacy.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
initRepoCommonFilterSearchDropdown,
initRepoCommonLanguageStats,
} from './repo-common.js';
import {initCitationFileCopyContent} from './citation.js';
import {initCompLabelEdit} from './comp/LabelEdit.js';
import {initRepoDiffConversationNav} from './repo-diff.js';
import attachTribute from './tribute.js';
Expand Down Expand Up @@ -505,6 +506,7 @@ export function initRepository() {
}

initRepoCloneLink();
initCitationFileCopyContent();
initRepoCommonLanguageStats();
initRepoSettingBranches();

Expand Down
52 changes: 51 additions & 1 deletion web_src/less/_repository.less
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@
border-right: none;
}

#download-btn {
#more-btn {
border-left: none;
}

Expand Down Expand Up @@ -2468,6 +2468,56 @@

// End of .repository

#cite-repo-modal {
#citation-panel {
width: 500px;

@media @mediaSm {
width: 100%;
}

input {
border-radius: 0;
padding: 5px 10px;
width: 50%;
line-height: 1.4;
}

.citation.button {
font-size: 13px;
padding: 7.5px 5px;
}

#citation-copy-content {
border-radius: 0;
padding: 5px 10px;
font-size: 1.2em;
line-height: 1.4;
}

#citation-copy-apa,
#citation-copy-bibtex {
border-right: none;
}

#goto-citation-btn {
border-left: none;
}

>:first-child {
border-radius: var(--border-radius) 0 0 var(--border-radius) !important;
}

>:last-child {
border-radius: 0 var(--border-radius) var(--border-radius) 0 !important;
}

.icon.button {
padding: 0 10px;
}
}
}

&.user-cards {
.list {
padding: 0;
Expand Down

0 comments on commit 9f8e778

Please sign in to comment.