From e6706df49ddc4ad7e02901c054b2f344894d7193 Mon Sep 17 00:00:00 2001 From: Benno Date: Wed, 30 Oct 2019 13:58:18 +0800 Subject: [PATCH 01/19] Create PR on Current Repository by Default (#8670) * 'update' * Send push tag event when release created * send tag create event while release created in UI * update to go v1.13 * fix gofmt error * fix #8576 create pull request on current repository by default --- routers/repo/compare.go | 28 ++++++++++++++++++++++++++++ templates/repo/diff/compare.tmpl | 7 ++++++- templates/repo/issue/list.tmpl | 2 +- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/routers/repo/compare.go b/routers/repo/compare.go index f8534f68b7..b9e14abfb8 100644 --- a/routers/repo/compare.go +++ b/routers/repo/compare.go @@ -339,12 +339,40 @@ func PrepareCompareDiff( return false } +// parseBaseRepoInfo parse base repository if current repo is forked. +// The "base" here means the repository where current repo forks from, +// not the repository fetch from current URL. +func parseBaseRepoInfo(ctx *context.Context, repo *models.Repository) error { + if !repo.IsFork { + return nil + } + if err := repo.GetBaseRepo(); err != nil { + return err + } + if err := repo.BaseRepo.GetOwnerName(); err != nil { + return err + } + baseGitRepo, err := git.OpenRepository(models.RepoPath(repo.BaseRepo.OwnerName, repo.BaseRepo.Name)) + if err != nil { + return err + } + ctx.Data["BaseRepoBranches"], err = baseGitRepo.GetBranches() + if err != nil { + return err + } + return nil +} + // CompareDiff show different from one commit to another commit func CompareDiff(ctx *context.Context) { headUser, headRepo, headGitRepo, compareInfo, baseBranch, headBranch := ParseCompareInfo(ctx) if ctx.Written() { return } + if err := parseBaseRepoInfo(ctx, headRepo); err != nil { + ctx.ServerError("parseBaseRepoInfo", err) + return + } nothingToCompare := PrepareCompareDiff(ctx, headUser, headRepo, headGitRepo, compareInfo, baseBranch, headBranch) if ctx.Written() { diff --git a/templates/repo/diff/compare.tmpl b/templates/repo/diff/compare.tmpl index 1c8942d42f..50a51c44ac 100644 --- a/templates/repo/diff/compare.tmpl +++ b/templates/repo/diff/compare.tmpl @@ -28,6 +28,11 @@ {{range .Branches}}
{{$.BaseName}}:{{.}}
{{end}} + {{if .Repository.IsFork}} + {{range .BaseRepoBranches}} +
{{$.PullRequestCtx.BaseRepo.OwnerName}}:{{.}}
+ {{end}} + {{end}} @@ -54,7 +59,7 @@ {{if .IsNothingToCompare}}
{{.i18n.Tr "repo.pulls.nothing_to_compare"}}
- {{else if .PageIsComparePull}} + {{else if .PageIsComparePull}} {{if .HasPullRequest}}
{{.i18n.Tr "repo.pulls.has_pull_request" $.RepoLink $.RepoRelPath .PullRequest.Index | Safe}} diff --git a/templates/repo/issue/list.tmpl b/templates/repo/issue/list.tmpl index 9b354a6800..d68e6dac26 100644 --- a/templates/repo/issue/list.tmpl +++ b/templates/repo/issue/list.tmpl @@ -14,7 +14,7 @@ {{if .PageIsIssueList}} {{.i18n.Tr "repo.issues.new"}} {{else}} - {{.i18n.Tr "repo.pulls.new"}} + {{.i18n.Tr "repo.pulls.new"}} {{end}}
{{else}} From 56ebc0c003349cea1c919c9dd408fc83ee79274e Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Wed, 30 Oct 2019 06:01:01 +0000 Subject: [PATCH 02/19] [skip ci] Updated translations via Crowdin --- options/locale/locale_zh-CN.ini | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 6a0ebed2be..594231262f 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -259,6 +259,7 @@ openid_signin_desc=输入您的 OpenID URI。例如: https://anne.me、bob.openi disable_forgot_password_mail=帐户恢复功能已被禁用。请与网站管理员联系。 email_domain_blacklisted=您不能使用您的电子邮件地址注册。 authorize_application=应用授权 +authorize_redirect_notice=如果您授权此应用,您将会被重定向到 %s。 authorize_application_created_by=此应用由%s创建。 authorize_application_description=如果您允许,它将能够读取和修改您的所有帐户信息,包括私人仓库和组织。 authorize_title=授权 %s 访问您的帐户? @@ -701,6 +702,7 @@ editor.preview_changes=预览变更 editor.cannot_edit_lfs_files=无法在 web 界面中编辑 lfs 文件。 editor.cannot_edit_non_text_files=网页不能编辑二进制文件。 editor.edit_this_file=编辑文件 +editor.this_file_locked=文件已锁定 editor.must_be_on_a_branch=您必须在某个分支上才能对此文件进行修改操作。 editor.fork_before_edit=您必须在派生这个仓库才能对此文件进行修改操作 editor.delete_this_file=删除文件 @@ -800,6 +802,7 @@ issues.delete_branch_at=`于 %[2]s 删除了分支 %[1]s` issues.open_tab=%d 个开启中 issues.close_tab=%d 个已关闭 issues.filter_label=标签筛选 +issues.filter_label_exclude=`使用 alt + 鼠标左键 / 回车 排除标签` issues.filter_label_no_select=所有标签 issues.filter_milestone=里程碑筛选 issues.filter_milestone_no_select=所有里程碑 @@ -974,6 +977,7 @@ issues.review.review=评审 issues.review.reviewers=评审人 issues.review.show_outdated=显示过时的 issues.review.hide_outdated=隐藏过时的 +issues.assignee.error=因为未知原因,并非所有的指派都成功。 pulls.desc=启用合并请求和代码评审。 pulls.new=创建合并请求 @@ -1332,6 +1336,7 @@ settings.protect_this_branch=启用分支保护 settings.protect_this_branch_desc=防止删除并禁用 Git 强制推送到分支。 settings.protect_whitelist_committers=启用推送白名单 settings.protect_whitelist_committers_desc=允许白名单用户或团队推向此分支 (但不强制推送)。 +settings.protect_whitelist_deploy_keys=拥有推送权限的部署密钥白名单 settings.protect_whitelist_users=推送白名单用户: settings.protect_whitelist_search_users=搜索用户... settings.protect_whitelist_teams=推送白名单团队: @@ -1373,6 +1378,21 @@ settings.unarchive.text=取消存档将恢复仓库接收提交,推送,新 settings.unarchive.success=仓库已成功取消归档。 settings.unarchive.error=仓库在撤销归档时出现异常。请通过日志获取详细信息。 settings.update_avatar_success=仓库头像已经更新。 +settings.lfs=LFS +settings.lfs_filelist=存储在此仓库中的 LFS 文件 +settings.lfs_no_lfs_files=此仓库中没有 LFS 文件 +settings.lfs_findcommits=查找提交 +settings.lfs_lfs_file_no_commits=没有找到关于此 LFS 文件的提交 +settings.lfs_delete=删除 OID 为 %s 的 LFS 文件 +settings.lfs_delete_warning=删除一个 LFS 文件可能导致签出时显示'对象不存在'的错误。确定继续吗? +settings.lfs_findpointerfiles=查找指针文件 +settings.lfs_pointers.found=找到 %d 个块指针 - %d 个关联, %d 个未关联(%d 个从仓库丢失) +settings.lfs_pointers.sha=Blob SHA +settings.lfs_pointers.oid=OID +settings.lfs_pointers.inRepo=在仓库中 +settings.lfs_pointers.exists=在仓库中存在 +settings.lfs_pointers.accessible=用户可访问 +settings.lfs_pointers.associateAccessible=关联可访问的 %d OID diff.browse_source=浏览代码 diff.parent=父节点 From f694bb45d79dcc093bc6332eabb3af063bc6b088 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 30 Oct 2019 16:36:25 +0800 Subject: [PATCH 03/19] Move issue change content from models to service (#8711) * Move issue change content from models to service * fix lint --- models/issue.go | 43 +------------------------ modules/notification/webhook/webhook.go | 38 ++++++++++++++++++++++ routers/repo/issue.go | 2 +- services/issue/content.go | 23 +++++++++++++ 4 files changed, 63 insertions(+), 43 deletions(-) create mode 100644 services/issue/content.go diff --git a/models/issue.go b/models/issue.go index b4bd190aa4..17205cc2fa 100644 --- a/models/issue.go +++ b/models/issue.go @@ -750,7 +750,6 @@ func (issue *Issue) UpdateAttachments(uuids []string) (err error) { // ChangeContent changes issue content, as the given user. func (issue *Issue) ChangeContent(doer *User, content string) (err error) { - oldContent := issue.Content issue.Content = content sess := x.NewSession() @@ -769,47 +768,7 @@ func (issue *Issue) ChangeContent(doer *User, content string) (err error) { return err } - if err = sess.Commit(); err != nil { - return err - } - sess.Close() - - mode, _ := AccessLevel(issue.Poster, issue.Repo) - if issue.IsPull { - issue.PullRequest.Issue = issue - err = PrepareWebhooks(issue.Repo, HookEventPullRequest, &api.PullRequestPayload{ - Action: api.HookIssueEdited, - Index: issue.Index, - Changes: &api.ChangesPayload{ - Body: &api.ChangesFromPayload{ - From: oldContent, - }, - }, - PullRequest: issue.PullRequest.APIFormat(), - Repository: issue.Repo.APIFormat(mode), - Sender: doer.APIFormat(), - }) - } else { - err = PrepareWebhooks(issue.Repo, HookEventIssues, &api.IssuePayload{ - Action: api.HookIssueEdited, - Index: issue.Index, - Changes: &api.ChangesPayload{ - Body: &api.ChangesFromPayload{ - From: oldContent, - }, - }, - Issue: issue.APIFormat(), - Repository: issue.Repo.APIFormat(mode), - Sender: doer.APIFormat(), - }) - } - if err != nil { - log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err) - } else { - go HookQueue.Add(issue.RepoID) - } - - return nil + return sess.Commit() } // GetTasks returns the amount of tasks in the issues content diff --git a/modules/notification/webhook/webhook.go b/modules/notification/webhook/webhook.go index bd7c8b29d3..a2af152edd 100644 --- a/modules/notification/webhook/webhook.go +++ b/modules/notification/webhook/webhook.go @@ -277,3 +277,41 @@ func (m *webhookNotifier) NotifyNewIssue(issue *models.Issue) { go models.HookQueue.Add(issue.RepoID) } } + +func (m *webhookNotifier) NotifyIssueChangeContent(doer *models.User, issue *models.Issue, oldContent string) { + mode, _ := models.AccessLevel(issue.Poster, issue.Repo) + var err error + if issue.IsPull { + issue.PullRequest.Issue = issue + err = models.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{ + Action: api.HookIssueEdited, + Index: issue.Index, + Changes: &api.ChangesPayload{ + Body: &api.ChangesFromPayload{ + From: oldContent, + }, + }, + PullRequest: issue.PullRequest.APIFormat(), + Repository: issue.Repo.APIFormat(mode), + Sender: doer.APIFormat(), + }) + } else { + err = models.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{ + Action: api.HookIssueEdited, + Index: issue.Index, + Changes: &api.ChangesPayload{ + Body: &api.ChangesFromPayload{ + From: oldContent, + }, + }, + Issue: issue.APIFormat(), + Repository: issue.Repo.APIFormat(mode), + Sender: doer.APIFormat(), + }) + } + if err != nil { + log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err) + } else { + go models.HookQueue.Add(issue.RepoID) + } +} diff --git a/routers/repo/issue.go b/routers/repo/issue.go index 12ff0a054c..ac405a1c29 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -1066,7 +1066,7 @@ func UpdateIssueContent(ctx *context.Context) { } content := ctx.Query("content") - if err := issue.ChangeContent(ctx.User, content); err != nil { + if err := issue_service.ChangeContent(issue, ctx.User, content); err != nil { ctx.ServerError("ChangeContent", err) return } diff --git a/services/issue/content.go b/services/issue/content.go new file mode 100644 index 0000000000..1081e30b5d --- /dev/null +++ b/services/issue/content.go @@ -0,0 +1,23 @@ +// Copyright 2019 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package issue + +import ( + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/notification" +) + +// ChangeContent changes issue content, as the given user. +func ChangeContent(issue *models.Issue, doer *models.User, content string) (err error) { + oldContent := issue.Content + + if err := issue.ChangeContent(doer, content); err != nil { + return err + } + + notification.NotifyIssueChangeContent(doer, issue, oldContent) + + return nil +} From ac6accef092ea5a983a4a8ee35282246fc3c6fc5 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 30 Oct 2019 18:02:46 +0800 Subject: [PATCH 04/19] Move webhook codes from service to webhook notification (#8712) * Move webhook codes from service to webhook notification * move deletecomment webhook to notifications * fix notification --- modules/notification/indexer/indexer.go | 5 ++ modules/notification/webhook/webhook.go | 83 +++++++++++++++++++++++++ routers/api/v1/repo/issue_comment.go | 7 --- routers/repo/issue.go | 8 +-- services/comments/comments.go | 74 ++-------------------- 5 files changed, 94 insertions(+), 83 deletions(-) diff --git a/modules/notification/indexer/indexer.go b/modules/notification/indexer/indexer.go index 453eb0c295..13baa76ac0 100644 --- a/modules/notification/indexer/indexer.go +++ b/modules/notification/indexer/indexer.go @@ -74,6 +74,11 @@ func (r *indexerNotifier) NotifyUpdateComment(doer *models.User, c *models.Comme func (r *indexerNotifier) NotifyDeleteComment(doer *models.User, comment *models.Comment) { if comment.Type == models.CommentTypeComment { + if err := comment.LoadIssue(); err != nil { + log.Error("LoadIssue: %v", err) + return + } + var found bool if comment.Issue.Comments != nil { for i := 0; i < len(comment.Issue.Comments); i++ { diff --git a/modules/notification/webhook/webhook.go b/modules/notification/webhook/webhook.go index a2af152edd..b4629ac56d 100644 --- a/modules/notification/webhook/webhook.go +++ b/modules/notification/webhook/webhook.go @@ -315,3 +315,86 @@ func (m *webhookNotifier) NotifyIssueChangeContent(doer *models.User, issue *mod go models.HookQueue.Add(issue.RepoID) } } + +func (m *webhookNotifier) NotifyUpdateComment(doer *models.User, c *models.Comment, oldContent string) { + if err := c.LoadPoster(); err != nil { + log.Error("LoadPoster: %v", err) + return + } + if err := c.LoadIssue(); err != nil { + log.Error("LoadIssue: %v", err) + return + } + + if err := c.Issue.LoadAttributes(); err != nil { + log.Error("LoadAttributes: %v", err) + return + } + + mode, _ := models.AccessLevel(doer, c.Issue.Repo) + if err := models.PrepareWebhooks(c.Issue.Repo, models.HookEventIssueComment, &api.IssueCommentPayload{ + Action: api.HookIssueCommentEdited, + Issue: c.Issue.APIFormat(), + Comment: c.APIFormat(), + Changes: &api.ChangesPayload{ + Body: &api.ChangesFromPayload{ + From: oldContent, + }, + }, + Repository: c.Issue.Repo.APIFormat(mode), + Sender: doer.APIFormat(), + IsPull: c.Issue.IsPull, + }); err != nil { + log.Error("PrepareWebhooks [comment_id: %d]: %v", c.ID, err) + } else { + go models.HookQueue.Add(c.Issue.Repo.ID) + } +} + +func (m *webhookNotifier) NotifyCreateIssueComment(doer *models.User, repo *models.Repository, + issue *models.Issue, comment *models.Comment) { + mode, _ := models.AccessLevel(doer, repo) + if err := models.PrepareWebhooks(repo, models.HookEventIssueComment, &api.IssueCommentPayload{ + Action: api.HookIssueCommentCreated, + Issue: issue.APIFormat(), + Comment: comment.APIFormat(), + Repository: repo.APIFormat(mode), + Sender: doer.APIFormat(), + IsPull: issue.IsPull, + }); err != nil { + log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err) + } else { + go models.HookQueue.Add(repo.ID) + } +} + +func (m *webhookNotifier) NotifyDeleteComment(doer *models.User, comment *models.Comment) { + if err := comment.LoadPoster(); err != nil { + log.Error("LoadPoster: %v", err) + return + } + if err := comment.LoadIssue(); err != nil { + log.Error("LoadIssue: %v", err) + return + } + + if err := comment.Issue.LoadAttributes(); err != nil { + log.Error("LoadAttributes: %v", err) + return + } + + mode, _ := models.AccessLevel(doer, comment.Issue.Repo) + + if err := models.PrepareWebhooks(comment.Issue.Repo, models.HookEventIssueComment, &api.IssueCommentPayload{ + Action: api.HookIssueCommentDeleted, + Issue: comment.Issue.APIFormat(), + Comment: comment.APIFormat(), + Repository: comment.Issue.Repo.APIFormat(mode), + Sender: doer.APIFormat(), + IsPull: comment.Issue.IsPull, + }); err != nil { + log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err) + } else { + go models.HookQueue.Add(comment.Issue.Repo.ID) + } +} diff --git a/routers/api/v1/repo/issue_comment.go b/routers/api/v1/repo/issue_comment.go index 60796031a5..3a5f6d2447 100644 --- a/routers/api/v1/repo/issue_comment.go +++ b/routers/api/v1/repo/issue_comment.go @@ -10,7 +10,6 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/notification" api "code.gitea.io/gitea/modules/structs" comment_service "code.gitea.io/gitea/services/comments" ) @@ -196,8 +195,6 @@ func CreateIssueComment(ctx *context.APIContext, form api.CreateIssueCommentOpti return } - notification.NotifyCreateIssueComment(ctx.User, ctx.Repo.Repository, issue, comment) - ctx.JSON(201, comment.APIFormat()) } @@ -305,8 +302,6 @@ func editIssueComment(ctx *context.APIContext, form api.EditIssueCommentOption) return } - notification.NotifyUpdateComment(ctx.User, comment, oldContent) - ctx.JSON(200, comment.APIFormat()) } @@ -396,7 +391,5 @@ func deleteIssueComment(ctx *context.APIContext) { return } - notification.NotifyDeleteComment(ctx.User, comment) - ctx.Status(204) } diff --git a/routers/repo/issue.go b/routers/repo/issue.go index ac405a1c29..04c718d5b9 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -1324,8 +1324,6 @@ func NewComment(ctx *context.Context, form auth.CreateCommentForm) { return } - notification.NotifyCreateIssueComment(ctx.User, ctx.Repo.Repository, issue, comment) - log.Trace("Comment created: %d/%d/%d", ctx.Repo.Repository.ID, issue.ID, comment.ID) } @@ -1375,8 +1373,6 @@ func UpdateCommentContent(ctx *context.Context) { ctx.ServerError("UpdateAttachments", err) } - notification.NotifyUpdateComment(ctx.User, comment, oldContent) - ctx.JSON(200, map[string]interface{}{ "content": string(markdown.Render([]byte(comment.Content), ctx.Query("context"), ctx.Repo.Repository.ComposeMetas())), "attachments": attachmentsHTML(ctx, comment.Attachments), @@ -1404,13 +1400,11 @@ func DeleteComment(ctx *context.Context) { return } - if err = models.DeleteComment(comment, ctx.User); err != nil { + if err = comment_service.DeleteComment(comment, ctx.User); err != nil { ctx.ServerError("DeleteCommentByID", err) return } - notification.NotifyDeleteComment(ctx.User, comment) - ctx.Status(200) } diff --git a/services/comments/comments.go b/services/comments/comments.go index 010c0aaac7..1ae5e2743f 100644 --- a/services/comments/comments.go +++ b/services/comments/comments.go @@ -11,9 +11,8 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/notification" "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/services/gitdiff" ) @@ -31,19 +30,8 @@ func CreateIssueComment(doer *models.User, repo *models.Repository, issue *model return nil, err } - mode, _ := models.AccessLevel(doer, repo) - if err = models.PrepareWebhooks(repo, models.HookEventIssueComment, &api.IssueCommentPayload{ - Action: api.HookIssueCommentCreated, - Issue: issue.APIFormat(), - Comment: comment.APIFormat(), - Repository: repo.APIFormat(mode), - Sender: doer.APIFormat(), - IsPull: issue.IsPull, - }); err != nil { - log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err) - } else { - go models.HookQueue.Add(repo.ID) - } + notification.NotifyCreateIssueComment(doer, repo, issue, comment) + return comment, nil } @@ -106,35 +94,7 @@ func UpdateComment(c *models.Comment, doer *models.User, oldContent string) erro return err } - if err := c.LoadPoster(); err != nil { - return err - } - if err := c.LoadIssue(); err != nil { - return err - } - - if err := c.Issue.LoadAttributes(); err != nil { - return err - } - - mode, _ := models.AccessLevel(doer, c.Issue.Repo) - if err := models.PrepareWebhooks(c.Issue.Repo, models.HookEventIssueComment, &api.IssueCommentPayload{ - Action: api.HookIssueCommentEdited, - Issue: c.Issue.APIFormat(), - Comment: c.APIFormat(), - Changes: &api.ChangesPayload{ - Body: &api.ChangesFromPayload{ - From: oldContent, - }, - }, - Repository: c.Issue.Repo.APIFormat(mode), - Sender: doer.APIFormat(), - IsPull: c.Issue.IsPull, - }); err != nil { - log.Error("PrepareWebhooks [comment_id: %d]: %v", c.ID, err) - } else { - go models.HookQueue.Add(c.Issue.Repo.ID) - } + notification.NotifyUpdateComment(doer, c, oldContent) return nil } @@ -145,31 +105,7 @@ func DeleteComment(comment *models.Comment, doer *models.User) error { return err } - if err := comment.LoadPoster(); err != nil { - return err - } - if err := comment.LoadIssue(); err != nil { - return err - } - - if err := comment.Issue.LoadAttributes(); err != nil { - return err - } - - mode, _ := models.AccessLevel(doer, comment.Issue.Repo) - - if err := models.PrepareWebhooks(comment.Issue.Repo, models.HookEventIssueComment, &api.IssueCommentPayload{ - Action: api.HookIssueCommentDeleted, - Issue: comment.Issue.APIFormat(), - Comment: comment.APIFormat(), - Repository: comment.Issue.Repo.APIFormat(mode), - Sender: doer.APIFormat(), - IsPull: comment.Issue.IsPull, - }); err != nil { - log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err) - } else { - go models.HookQueue.Add(comment.Issue.Repo.ID) - } + notification.NotifyDeleteComment(doer, comment) return nil } From f9944c0e6929f1c314d0a6e8d38a5592ba6eee2c Mon Sep 17 00:00:00 2001 From: guillep2k <18600385+guillep2k@users.noreply.github.com> Date: Wed, 30 Oct 2019 09:43:59 -0300 Subject: [PATCH 05/19] Configurable close and reopen keywords for PRs (#8120) * Add settings for CloseKeywords and ReopenKeywords * Fix and improve tests * Use sync.Once() for initialization * Fix unintended exported function --- custom/conf/app.ini.sample | 4 + .../doc/advanced/config-cheat-sheet.en-us.md | 4 + modules/references/references.go | 62 ++++-- modules/references/references_test.go | 198 ++++++++++++------ modules/setting/repository.go | 8 + 5 files changed, 199 insertions(+), 77 deletions(-) diff --git a/custom/conf/app.ini.sample b/custom/conf/app.ini.sample index f0204bb06e..e6ccab95d9 100644 --- a/custom/conf/app.ini.sample +++ b/custom/conf/app.ini.sample @@ -69,6 +69,10 @@ MAX_FILES = 5 [repository.pull-request] ; List of prefixes used in Pull Request title to mark them as Work In Progress WORK_IN_PROGRESS_PREFIXES=WIP:,[WIP] +; List of keywords used in Pull Request comments to automatically close a related issue +CLOSE_KEYWORDS=close,closes,closed,fix,fixes,fixed,resolve,resolves,resolved +; List of keywords used in Pull Request comments to automatically reopen a related issue +REOPEN_KEYWORDS=reopen,reopens,reopened [repository.issue] ; List of reasons why a Pull Request or Issue can be locked diff --git a/docs/content/doc/advanced/config-cheat-sheet.en-us.md b/docs/content/doc/advanced/config-cheat-sheet.en-us.md index c2744b2958..bcf871a3a4 100644 --- a/docs/content/doc/advanced/config-cheat-sheet.en-us.md +++ b/docs/content/doc/advanced/config-cheat-sheet.en-us.md @@ -71,6 +71,10 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`. - `WORK_IN_PROGRESS_PREFIXES`: **WIP:,\[WIP\]**: List of prefixes used in Pull Request title to mark them as Work In Progress +- `CLOSE_KEYWORDS`: **close**, **closes**, **closed**, **fix**, **fixes**, **fixed**, **resolve**, **resolves**, **resolved**: List of + keywords used in Pull Request comments to automatically close a related issue +- `REOPEN_KEYWORDS`: **reopen**, **reopens**, **reopened**: List of keywords used in Pull Request comments to automatically reopen + a related issue ### Repository - Issue (`repository.issue`) diff --git a/modules/references/references.go b/modules/references/references.go index 9c74d0d081..58a8da2895 100644 --- a/modules/references/references.go +++ b/modules/references/references.go @@ -11,6 +11,7 @@ import ( "strings" "sync" + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup/mdstripper" "code.gitea.io/gitea/modules/setting" ) @@ -35,12 +36,8 @@ var ( // e.g. gogits/gogs#12345 crossReferenceIssueNumericPattern = regexp.MustCompile(`(?:\s|^|\(|\[)([0-9a-zA-Z-_\.]+/[0-9a-zA-Z-_\.]+#[0-9]+)(?:\s|$|\)|\]|\.(\s|$))`) - // Same as GitHub. See - // https://help.github.com/articles/closing-issues-via-commit-messages - issueCloseKeywords = []string{"close", "closes", "closed", "fix", "fixes", "fixed", "resolve", "resolves", "resolved"} - issueReopenKeywords = []string{"reopen", "reopens", "reopened"} - issueCloseKeywordsPat, issueReopenKeywordsPat *regexp.Regexp + issueKeywordsOnce sync.Once giteaHostInit sync.Once giteaHost string @@ -107,13 +104,40 @@ type RefSpan struct { End int } -func makeKeywordsPat(keywords []string) *regexp.Regexp { - return regexp.MustCompile(`(?i)(?:\s|^|\(|\[)(` + strings.Join(keywords, `|`) + `):? $`) +func makeKeywordsPat(words []string) *regexp.Regexp { + acceptedWords := parseKeywords(words) + if len(acceptedWords) == 0 { + // Never match + return nil + } + return regexp.MustCompile(`(?i)(?:\s|^|\(|\[)(` + strings.Join(acceptedWords, `|`) + `):? $`) } -func init() { - issueCloseKeywordsPat = makeKeywordsPat(issueCloseKeywords) - issueReopenKeywordsPat = makeKeywordsPat(issueReopenKeywords) +func parseKeywords(words []string) []string { + acceptedWords := make([]string, 0, 5) + wordPat := regexp.MustCompile(`^[\pL]+$`) + for _, word := range words { + word = strings.ToLower(strings.TrimSpace(word)) + // Accept Unicode letter class runes (a-z, á, à, ä, ) + if wordPat.MatchString(word) { + acceptedWords = append(acceptedWords, word) + } else { + log.Info("Invalid keyword: %s", word) + } + } + return acceptedWords +} + +func newKeywords() { + issueKeywordsOnce.Do(func() { + // Delay initialization until after the settings module is initialized + doNewKeywords(setting.Repository.PullRequest.CloseKeywords, setting.Repository.PullRequest.ReopenKeywords) + }) +} + +func doNewKeywords(close []string, reopen []string) { + issueCloseKeywordsPat = makeKeywordsPat(close) + issueReopenKeywordsPat = makeKeywordsPat(reopen) } // getGiteaHostName returns a normalized string with the local host name, with no scheme or port information @@ -310,13 +334,19 @@ func getCrossReference(content []byte, start, end int, fromLink bool) *rawRefere } func findActionKeywords(content []byte, start int) (XRefAction, *RefSpan) { - m := issueCloseKeywordsPat.FindSubmatchIndex(content[:start]) - if m != nil { - return XRefActionCloses, &RefSpan{Start: m[2], End: m[3]} + newKeywords() + var m []int + if issueCloseKeywordsPat != nil { + m = issueCloseKeywordsPat.FindSubmatchIndex(content[:start]) + if m != nil { + return XRefActionCloses, &RefSpan{Start: m[2], End: m[3]} + } } - m = issueReopenKeywordsPat.FindSubmatchIndex(content[:start]) - if m != nil { - return XRefActionReopens, &RefSpan{Start: m[2], End: m[3]} + if issueReopenKeywordsPat != nil { + m = issueReopenKeywordsPat.FindSubmatchIndex(content[:start]) + if m != nil { + return XRefActionReopens, &RefSpan{Start: m[2], End: m[3]} + } } return XRefActionNone, nil } diff --git a/modules/references/references_test.go b/modules/references/references_test.go index f8153ffe36..52e9b4ff52 100644 --- a/modules/references/references_test.go +++ b/modules/references/references_test.go @@ -12,161 +12,136 @@ import ( "github.com/stretchr/testify/assert" ) +type testFixture struct { + input string + expected []testResult +} + +type testResult struct { + Index int64 + Owner string + Name string + Issue string + Action XRefAction + RefLocation *RefSpan + ActionLocation *RefSpan +} + func TestFindAllIssueReferences(t *testing.T) { - type result struct { - Index int64 - Owner string - Name string - Issue string - Action XRefAction - RefLocation *RefSpan - ActionLocation *RefSpan - } - - type testFixture struct { - input string - expected []result - } - fixtures := []testFixture{ { "Simply closes: #29 yes", - []result{ + []testResult{ {29, "", "", "29", XRefActionCloses, &RefSpan{Start: 15, End: 18}, &RefSpan{Start: 7, End: 13}}, }, }, { "#123 no, this is a title.", - []result{}, + []testResult{}, }, { " #124 yes, this is a reference.", - []result{ + []testResult{ {124, "", "", "124", XRefActionNone, &RefSpan{Start: 0, End: 4}, nil}, }, }, { "```\nThis is a code block.\n#723 no, it's a code block.```", - []result{}, + []testResult{}, }, { "This `#724` no, it's inline code.", - []result{}, + []testResult{}, }, { "This user3/repo4#200 yes.", - []result{ + []testResult{ {200, "user3", "repo4", "200", XRefActionNone, &RefSpan{Start: 5, End: 20}, nil}, }, }, { "This [one](#919) no, this is a URL fragment.", - []result{}, + []testResult{}, }, { "This [two](/user2/repo1/issues/921) yes.", - []result{ + []testResult{ {921, "user2", "repo1", "921", XRefActionNone, nil, nil}, }, }, { "This [three](/user2/repo1/pulls/922) yes.", - []result{ + []testResult{ {922, "user2", "repo1", "922", XRefActionNone, nil, nil}, }, }, { "This [four](http://gitea.com:3000/user3/repo4/issues/203) yes.", - []result{ + []testResult{ {203, "user3", "repo4", "203", XRefActionNone, nil, nil}, }, }, { "This [five](http://github.com/user3/repo4/issues/204) no.", - []result{}, + []testResult{}, }, { "This http://gitea.com:3000/user4/repo5/201 no, bad URL.", - []result{}, + []testResult{}, }, { "This http://gitea.com:3000/user4/repo5/pulls/202 yes.", - []result{ + []testResult{ {202, "user4", "repo5", "202", XRefActionNone, nil, nil}, }, }, { "This http://GiTeA.COM:3000/user4/repo6/pulls/205 yes.", - []result{ + []testResult{ {205, "user4", "repo6", "205", XRefActionNone, nil, nil}, }, }, { "Reopens #15 yes", - []result{ + []testResult{ {15, "", "", "15", XRefActionReopens, &RefSpan{Start: 8, End: 11}, &RefSpan{Start: 0, End: 7}}, }, }, { "This closes #20 for you yes", - []result{ + []testResult{ {20, "", "", "20", XRefActionCloses, &RefSpan{Start: 12, End: 15}, &RefSpan{Start: 5, End: 11}}, }, }, { "Do you fix user6/repo6#300 ? yes", - []result{ + []testResult{ {300, "user6", "repo6", "300", XRefActionCloses, &RefSpan{Start: 11, End: 26}, &RefSpan{Start: 7, End: 10}}, }, }, { "For 999 #1235 no keyword, but yes", - []result{ + []testResult{ {1235, "", "", "1235", XRefActionNone, &RefSpan{Start: 8, End: 13}, nil}, }, }, { "Which abc. #9434 same as above", - []result{ + []testResult{ {9434, "", "", "9434", XRefActionNone, &RefSpan{Start: 11, End: 16}, nil}, }, }, { "This closes #600 and reopens #599", - []result{ + []testResult{ {600, "", "", "600", XRefActionCloses, &RefSpan{Start: 12, End: 16}, &RefSpan{Start: 5, End: 11}}, {599, "", "", "599", XRefActionReopens, &RefSpan{Start: 29, End: 33}, &RefSpan{Start: 21, End: 28}}, }, }, } - // Save original value for other tests that may rely on it - prevURL := setting.AppURL - setting.AppURL = "https://gitea.com:3000/" - - for _, fixture := range fixtures { - expraw := make([]*rawReference, len(fixture.expected)) - for i, e := range fixture.expected { - expraw[i] = &rawReference{ - index: e.Index, - owner: e.Owner, - name: e.Name, - action: e.Action, - issue: e.Issue, - refLocation: e.RefLocation, - actionLocation: e.ActionLocation, - } - } - expref := rawToIssueReferenceList(expraw) - refs := FindAllIssueReferencesMarkdown(fixture.input) - assert.EqualValues(t, expref, refs, "Failed to parse: {%s}", fixture.input) - rawrefs := findAllIssueReferencesMarkdown(fixture.input) - assert.EqualValues(t, expraw, rawrefs, "Failed to parse: {%s}", fixture.input) - } - - // Restore for other tests that may rely on the original value - setting.AppURL = prevURL + testFixtures(t, fixtures, "default") type alnumFixture struct { input string @@ -203,6 +178,35 @@ func TestFindAllIssueReferences(t *testing.T) { } } +func testFixtures(t *testing.T, fixtures []testFixture, context string) { + // Save original value for other tests that may rely on it + prevURL := setting.AppURL + setting.AppURL = "https://gitea.com:3000/" + + for _, fixture := range fixtures { + expraw := make([]*rawReference, len(fixture.expected)) + for i, e := range fixture.expected { + expraw[i] = &rawReference{ + index: e.Index, + owner: e.Owner, + name: e.Name, + action: e.Action, + issue: e.Issue, + refLocation: e.RefLocation, + actionLocation: e.ActionLocation, + } + } + expref := rawToIssueReferenceList(expraw) + refs := FindAllIssueReferencesMarkdown(fixture.input) + assert.EqualValues(t, expref, refs, "[%s] Failed to parse: {%s}", context, fixture.input) + rawrefs := findAllIssueReferencesMarkdown(fixture.input) + assert.EqualValues(t, expraw, rawrefs, "[%s] Failed to parse: {%s}", context, fixture.input) + } + + // Restore for other tests that may rely on the original value + setting.AppURL = prevURL +} + func TestRegExp_mentionPattern(t *testing.T) { trueTestCases := []string{ "@Unknwon", @@ -294,3 +298,75 @@ func TestRegExp_issueAlphanumericPattern(t *testing.T) { assert.False(t, issueAlphanumericPattern.MatchString(testCase)) } } + +func TestCustomizeCloseKeywords(t *testing.T) { + fixtures := []testFixture{ + { + "Simplemente cierra: #29 yes", + []testResult{ + {29, "", "", "29", XRefActionCloses, &RefSpan{Start: 20, End: 23}, &RefSpan{Start: 12, End: 18}}, + }, + }, + { + "Closes: #123 no, this English.", + []testResult{ + {123, "", "", "123", XRefActionNone, &RefSpan{Start: 8, End: 12}, nil}, + }, + }, + { + "Cerró user6/repo6#300 yes", + []testResult{ + {300, "user6", "repo6", "300", XRefActionCloses, &RefSpan{Start: 7, End: 22}, &RefSpan{Start: 0, End: 6}}, + }, + }, + { + "Reabre user3/repo4#200 yes", + []testResult{ + {200, "user3", "repo4", "200", XRefActionReopens, &RefSpan{Start: 7, End: 22}, &RefSpan{Start: 0, End: 6}}, + }, + }, + } + + issueKeywordsOnce.Do(func() {}) + + doNewKeywords([]string{"cierra", "cerró"}, []string{"reabre"}) + testFixtures(t, fixtures, "spanish") + + // Restore default settings + doNewKeywords(setting.Repository.PullRequest.CloseKeywords, setting.Repository.PullRequest.ReopenKeywords) +} + +func TestParseCloseKeywords(t *testing.T) { + // Test parsing of CloseKeywords and ReopenKeywords + assert.Len(t, parseKeywords([]string{""}), 0) + assert.Len(t, parseKeywords([]string{" aa ", " bb ", "99", "#", "", "this is", "cc"}), 3) + + for _, test := range []struct { + pattern string + match string + expected string + }{ + {"close", "This PR will close ", "close"}, + {"cerró", "cerró ", "cerró"}, + {"cerró", "AQUÍ SE CERRÓ: ", "CERRÓ"}, + {"закрывается", "закрывается ", "закрывается"}, + {"κλείνει", "κλείνει: ", "κλείνει"}, + {"关闭", "关闭 ", "关闭"}, + {"閉じます", "閉じます ", "閉じます"}, + {",$!", "", ""}, + {"1234", "", ""}, + } { + // The patern only needs to match the part that precedes the reference. + // getCrossReference() takes care of finding the reference itself. + pat := makeKeywordsPat([]string{test.pattern}) + if test.expected == "" { + assert.Nil(t, pat) + } else { + assert.NotNil(t, pat) + res := pat.FindAllStringSubmatch(test.match, -1) + assert.Len(t, res, 1) + assert.Len(t, res[0], 2) + assert.EqualValues(t, test.expected, res[0][1]) + } + } +} diff --git a/modules/setting/repository.go b/modules/setting/repository.go index 19c68d003f..3e183b6c98 100644 --- a/modules/setting/repository.go +++ b/modules/setting/repository.go @@ -59,6 +59,8 @@ var ( // Pull request settings PullRequest struct { WorkInProgressPrefixes []string + CloseKeywords []string + ReopenKeywords []string } `ini:"repository.pull-request"` // Issue Setting @@ -122,8 +124,14 @@ var ( // Pull request settings PullRequest: struct { WorkInProgressPrefixes []string + CloseKeywords []string + ReopenKeywords []string }{ WorkInProgressPrefixes: []string{"WIP:", "[WIP]"}, + // Same as GitHub. See + // https://help.github.com/articles/closing-issues-via-commit-messages + CloseKeywords: strings.Split("close,closes,closed,fix,fixes,fixed,resolve,resolves,resolved", ","), + ReopenKeywords: strings.Split("reopen,reopens,reopened", ","), }, // Issue settings From 7d9351779fb0d7c65adae3326077e8d84902c0d6 Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Wed, 30 Oct 2019 12:45:34 +0000 Subject: [PATCH 06/19] [skip ci] Updated translations via Crowdin --- options/locale/locale_pt-BR.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini index 71ed3ff0d4..762000edfc 100644 --- a/options/locale/locale_pt-BR.ini +++ b/options/locale/locale_pt-BR.ini @@ -702,6 +702,7 @@ editor.preview_changes=Visualizar alterações editor.cannot_edit_lfs_files=Arquivos LFS não podem ser editados na interface web. editor.cannot_edit_non_text_files=Arquivos binários não podem ser editados na interface web. editor.edit_this_file=Editar arquivo +editor.this_file_locked=Arquivo está bloqueado editor.must_be_on_a_branch=Você deve estar em um branch para propor alterações neste arquivo. editor.fork_before_edit=Você deve fazer um fork desse repositório para fazer ou propor alterações neste arquivo. editor.delete_this_file=Excluir arquivo From bc1775b490a39c42497dc782c1e2effc5af47715 Mon Sep 17 00:00:00 2001 From: jaqra <48099350+jaqra@users.noreply.github.com> Date: Wed, 30 Oct 2019 17:39:35 +0300 Subject: [PATCH 07/19] add __debug_bin file to gitignore (#8740) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 773b4726c0..331e26c3be 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ _test # MS VSCode .vscode +__debug_bin # Architecture specific extensions/prefixes *.[568vq] From bda70b848fafc0bc74326ac6860b11a500218679 Mon Sep 17 00:00:00 2001 From: zeripath Date: Wed, 30 Oct 2019 16:19:14 +0000 Subject: [PATCH 08/19] Update licenses (#8752) Replaces #8182 --- options/license/AAL | 6 +-- options/license/ADSL | 2 +- options/license/AFL-1.1 | 2 +- options/license/AGPL-3.0-only | 7 ++- options/license/AGPL-3.0-or-later | 7 ++- options/license/Adobe-2006 | 5 +- options/license/Aladdin | 5 +- options/license/Apache-1.1 | 5 +- options/license/Autoconf-exception-3.0 | 4 +- options/license/BSD-2-Clause | 2 +- options/license/BSD-2-Clause-FreeBSD | 5 +- options/license/BSD-3-Clause | 2 +- options/license/BSD-3-Clause-Clear | 4 +- options/license/BSD-4-Clause | 2 +- options/license/CC-BY-ND-2.0 | 2 +- options/license/CUA-OPL-1.0 | 4 +- options/license/Condor-1.1 | 11 ++--- options/license/Cube | 5 +- options/license/DSDP | 4 +- options/license/EUDatagrid | 4 +- options/license/EUPL-1.0 | 13 +++-- options/license/EUPL-1.1 | 4 +- options/license/Entessa | 5 +- options/license/Fair | 4 +- options/license/GFDL-1.3-only | 6 +-- options/license/GFDL-1.3-or-later | 6 +-- options/license/GL2PS | 4 +- options/license/GPL-2.0-only | 10 ++-- options/license/GPL-2.0-or-later | 6 +-- options/license/GPL-3.0-only | 9 ++-- options/license/GPL-3.0-or-later | 9 ++-- options/license/HPND | 6 +-- options/license/ICU | 5 +- options/license/ISC | 4 +- options/license/ImageMagick | 7 ++- options/license/Info-ZIP | 4 +- options/license/Intel | 4 +- options/license/Interbase-1.0 | 2 +- options/license/JSON | 4 +- options/license/JasPer-2.0 | 4 +- options/license/LAL-1.3 | 66 +++++++++++++------------- options/license/LGPL-2.0-only | 4 +- options/license/LGPL-2.0-or-later | 4 +- options/license/LGPL-3.0-only | 2 +- options/license/LGPL-3.0-or-later | 2 +- options/license/LPPL-1.0 | 4 +- options/license/LPPL-1.1 | 4 +- options/license/LPPL-1.2 | 4 +- options/license/LPPL-1.3a | 4 +- options/license/LPPL-1.3c | 4 +- options/license/MIT | 4 +- options/license/MIT-CMU | 35 ++++++-------- options/license/MPL-1.0 | 4 +- options/license/MPL-1.1 | 4 +- options/license/MTLL | 4 +- options/license/MakeIndex | 4 +- options/license/MirOS | 54 +-------------------- options/license/Multics | 7 ++- options/license/NBPL-1.0 | 11 ++--- options/license/NCSA | 5 +- options/license/NGPL | 4 +- options/license/NTP | 5 +- options/license/Naumen | 5 +- options/license/Net-SNMP | 18 +++---- options/license/OCLC-2.0 | 9 ++-- options/license/OLDAP-1.1 | 9 ++-- options/license/OLDAP-1.2 | 9 ++-- options/license/OLDAP-1.3 | 10 ++-- options/license/OLDAP-1.4 | 10 ++-- options/license/OLDAP-2.0 | 6 +-- options/license/OLDAP-2.0.1 | 6 +-- options/license/OLDAP-2.1 | 6 +-- options/license/OSET-PL-2.1 | 10 ++-- options/license/OSL-1.0 | 2 +- options/license/OpenSSL | 8 +--- options/license/PHP-3.0 | 5 +- options/license/PHP-3.01 | 5 +- options/license/Plexus | 2 +- options/license/PostgreSQL | 5 +- options/license/Python-2.0 | 6 +-- options/license/QPL-1.0 | 4 +- options/license/RPL-1.1 | 5 +- options/license/RPSL-1.0 | 4 +- options/license/RSCPL | 16 +++---- options/license/SGI-B-1.0 | 9 ++-- options/license/SGI-B-1.1 | 7 ++- options/license/SGI-B-2.0 | 6 +-- options/license/SISSL | 2 +- options/license/SISSL-1.2 | 25 +++++----- options/license/SMLNJ | 5 +- options/license/SMPPL | 5 +- options/license/Sleepycat | 12 ++--- options/license/TMate | 5 +- options/license/TORQUE-1.1 | 12 ++--- options/license/Unicode-DFS-2016 | 8 ++-- options/license/Unlicense | 13 ++--- options/license/VOSTROM | 5 +- options/license/VSL-1.0 | 5 +- options/license/Vim | 17 +++---- options/license/W3C-19980720 | 8 ++-- options/license/Wsuipa | 7 ++- options/license/X11 | 4 +- options/license/XFree86-1.1 | 4 +- options/license/Xnet | 5 +- options/license/ZPL-1.1 | 6 +-- options/license/ZPL-2.0 | 9 ++-- options/license/curl | 5 +- options/license/psfrag | 4 +- options/license/psutils | 6 +-- options/license/xinetd | 4 +- options/license/xpp | 5 +- 111 files changed, 303 insertions(+), 503 deletions(-) diff --git a/options/license/AAL b/options/license/AAL index c0612cc6e7..781ca0e7a3 100644 --- a/options/license/AAL +++ b/options/license/AAL @@ -1,7 +1,5 @@ -Attribution Assurance License - -Copyright (c) 2002 by AUTHOR PROFESSIONAL IDENTIFICATION * URL "PROMOTIONAL -SLOGAN FOR AUTHOR'S PROFESSIONAL PRACTICE" +Attribution Assurance License Copyright (c) 2002 by AUTHOR PROFESSIONAL IDENTIFICATION +* URL "PROMOTIONAL SLOGAN FOR AUTHOR'S PROFESSIONAL PRACTICE" All Rights Reserved ATTRIBUTION ASSURANCE LICENSE (adapted from the original BSD license) diff --git a/options/license/ADSL b/options/license/ADSL index d3017689d5..aef03b73bc 100644 --- a/options/license/ADSL +++ b/options/license/ADSL @@ -1,6 +1,6 @@ This software code is made available "AS IS" without warranties of any kind. You may copy, display, modify and redistribute the software code either by -itself or as incorporated into your code; provided that > you do not remove +itself or as incorporated into your code; provided that you do not remove any proprietary notices. Your use of this software code is at your own risk and you waive any claim against Amazon Digital Services, Inc. or its affiliates with respect to your use of this software code. (c) 2006 Amazon Digital Services, diff --git a/options/license/AFL-1.1 b/options/license/AFL-1.1 index 0b74d59e17..a505d889c3 100644 --- a/options/license/AFL-1.1 +++ b/options/license/AFL-1.1 @@ -4,7 +4,7 @@ Version 1.1 The Academic Free License applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following notice immediately following the copyright notice for the Original Work: -" Licensed under the Academic Free License version 1.1. " +"Licensed under the Academic Free License version 1.1." Grant of License. Licensor hereby grants to any person obtaining a copy of the Original Work ("You") a world-wide, royalty-free, non-exclusive, perpetual, diff --git a/options/license/AGPL-3.0-only b/options/license/AGPL-3.0-only index 82b56508cc..e37e32e4e8 100644 --- a/options/license/AGPL-3.0-only +++ b/options/license/AGPL-3.0-only @@ -2,7 +2,7 @@ GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007 -Copyright (C) 2007 Free Software Foundation, Inc. +Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -597,7 +597,7 @@ FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along -with this program. If not, see . +with this program. If not, see . Also add information on how to contact you by electronic and paper mail. @@ -610,5 +610,4 @@ programs; see section 13 for the specific requirements. You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For -more information on this, and how to apply and follow the GNU AGPL, see . +more information on this, and how to apply and follow the GNU AGPL, see . diff --git a/options/license/AGPL-3.0-or-later b/options/license/AGPL-3.0-or-later index 82b56508cc..e37e32e4e8 100644 --- a/options/license/AGPL-3.0-or-later +++ b/options/license/AGPL-3.0-or-later @@ -2,7 +2,7 @@ GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007 -Copyright (C) 2007 Free Software Foundation, Inc. +Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -597,7 +597,7 @@ FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along -with this program. If not, see . +with this program. If not, see . Also add information on how to contact you by electronic and paper mail. @@ -610,5 +610,4 @@ programs; see section 13 for the specific requirements. You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For -more information on this, and how to apply and follow the GNU AGPL, see . +more information on this, and how to apply and follow the GNU AGPL, see . diff --git a/options/license/Adobe-2006 b/options/license/Adobe-2006 index 553d247990..9e3828254b 100644 --- a/options/license/Adobe-2006 +++ b/options/license/Adobe-2006 @@ -1,6 +1,5 @@ -Adobe Systems Incorporated(r) Source Code License Agreement - -Copyright(c) 2006 Adobe Systems Incorporated. All rights reserved. +Adobe Systems Incorporated(r) Source Code License Agreement Copyright(c) 2006 +Adobe Systems Incorporated. All rights reserved. Please read this Source Code License Agreement carefully before using the source code. diff --git a/options/license/Aladdin b/options/license/Aladdin index f93c7e85f0..204cb1f3d7 100644 --- a/options/license/Aladdin +++ b/options/license/Aladdin @@ -1,8 +1,7 @@ Aladdin Free Public License -(Version 8, November 18, 1999) - -Copyright (C) 1994, 1995, 1997, 1998, 1999 Aladdin Enterprises, +(Version 8, November 18, 1999) Copyright (C) 1994, 1995, 1997, 1998, 1999 +Aladdin Enterprises, Menlo Park, California, U.S.A. All rights reserved. NOTE: This License is not the same as any of the GNU Licenses published by the Free Software Foundation. diff --git a/options/license/Apache-1.1 b/options/license/Apache-1.1 index b2f7de6b3c..62c4061a31 100644 --- a/options/license/Apache-1.1 +++ b/options/license/Apache-1.1 @@ -1,6 +1,5 @@ -Apache License 1.1 - -Copyright (c) 2000 The Apache Software Foundation . All rights reserved. +Apache License 1.1 Copyright (c) 2000 The Apache Software Foundation. All +rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/options/license/Autoconf-exception-3.0 b/options/license/Autoconf-exception-3.0 index 439da3cc5f..346c459f80 100644 --- a/options/license/Autoconf-exception-3.0 +++ b/options/license/Autoconf-exception-3.0 @@ -1,8 +1,6 @@ AUTOCONF CONFIGURE SCRIPT EXCEPTION -Version 3.0, 18 August 2009 - -Copyright © 2009 Free Software Foundation, Inc. +Version 3.0, 18 August 2009 Copyright © 2009 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. diff --git a/options/license/BSD-2-Clause b/options/license/BSD-2-Clause index c2e480ee4f..2d2bab1127 100644 --- a/options/license/BSD-2-Clause +++ b/options/license/BSD-2-Clause @@ -1,4 +1,4 @@ -Copyright (c) . All rights reserved. +Copyright (c) . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/options/license/BSD-2-Clause-FreeBSD b/options/license/BSD-2-Clause-FreeBSD index aadf852dfb..004ec94575 100644 --- a/options/license/BSD-2-Clause-FreeBSD +++ b/options/license/BSD-2-Clause-FreeBSD @@ -1,6 +1,5 @@ -The FreeBSD Copyright - -Copyright 1992-2012 The FreeBSD Project. All rights reserved. +The FreeBSD Copyright Copyright 1992-2012 The FreeBSD Project. All rights +reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/options/license/BSD-3-Clause b/options/license/BSD-3-Clause index b2a9c51f55..0741db789e 100644 --- a/options/license/BSD-3-Clause +++ b/options/license/BSD-3-Clause @@ -1,4 +1,4 @@ -Copyright (c) . All rights reserved. +Copyright (c) . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/options/license/BSD-3-Clause-Clear b/options/license/BSD-3-Clause-Clear index 8f9a4937a7..40066db07d 100644 --- a/options/license/BSD-3-Clause-Clear +++ b/options/license/BSD-3-Clause-Clear @@ -1,6 +1,4 @@ -The Clear BSD License - -Copyright (c) [xxxx]-[xxxx] [Owner Organization] +The Clear BSD License Copyright (c) [xxxx]-[xxxx] [Owner Organization] All rights reserved. diff --git a/options/license/BSD-4-Clause b/options/license/BSD-4-Clause index 09c07fb1d2..34b7498064 100644 --- a/options/license/BSD-4-Clause +++ b/options/license/BSD-4-Clause @@ -1,4 +1,4 @@ -Copyright (c) . All rights reserved. +Copyright (c) . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/options/license/CC-BY-ND-2.0 b/options/license/CC-BY-ND-2.0 index 30ef1cb4ec..1a41ece832 100644 --- a/options/license/CC-BY-ND-2.0 +++ b/options/license/CC-BY-ND-2.0 @@ -202,4 +202,4 @@ consent of Creative Commons. Any permitted use will be in compliance with Creative Commons' then-current trademark usage guidelines, as may be published on its website or otherwise made available upon request from time to time. -Creative Commons may be contacted at http s ://creativecommons.org/. +Creative Commons may be contacted at https://creativecommons.org/. diff --git a/options/license/CUA-OPL-1.0 b/options/license/CUA-OPL-1.0 index 9ce67d9a9c..3c46119b11 100644 --- a/options/license/CUA-OPL-1.0 +++ b/options/license/CUA-OPL-1.0 @@ -378,7 +378,7 @@ portions of the Covered Code under Your choice of the NPL or the alternative licenses, if any, specified by the Initial Developer in the file described in Exhibit A. EXHIBIT A - CUA Office Public License. -" The contents of this file are subject to the CUA Office Public License Version +"The contents of this file are subject to the CUA Office Public License Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://cuaoffice.sourceforge.net/ @@ -402,7 +402,7 @@ to allow others to use your version of this file under the CUAPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the [___] License. If you do not delete the provisions above, a recipient may use your version of this file under either -the CUAPL or the [___] License. " +the CUAPL or the [___] License." [NOTE: The text of this Exhibit A may differ slightly from the text of the notices in the Source Code files of the Original Code. You should use the diff --git a/options/license/Condor-1.1 b/options/license/Condor-1.1 index 44961c85a3..e857135f63 100644 --- a/options/license/Condor-1.1 +++ b/options/license/Condor-1.1 @@ -1,11 +1,10 @@ Condor Public License -Version 1.1, October 30, 2003 - -Copyright © 1990-2006 Condor Team, Computer Sciences Department, University -of Wisconsin-Madison, Madison, WI. All Rights Reserved. For more information -contact: Condor Team, Attention: Professor Miron Livny, Dept of Computer Sciences, -1210 W. Dayton St., Madison, WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu. +Version 1.1, October 30, 2003 Copyright © 1990-2006 Condor Team, Computer +Sciences Department, University of Wisconsin-Madison, Madison, WI. All Rights +Reserved. For more information contact: Condor Team, Attention: Professor +Miron Livny, Dept of Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685, +(608) 262-0856 or miron@cs.wisc.edu. This software referred to as the Condor® Version 6.x software ("Software") was developed by the Condor Project, Condor Team, Computer Sciences Department, diff --git a/options/license/Cube b/options/license/Cube index 21ba979c6e..707afcc04c 100644 --- a/options/license/Cube +++ b/options/license/Cube @@ -1,6 +1,5 @@ -Cube game engine source code, 20 dec 2003 release. - -Copyright (C) 2001-2003 Wouter van Oortmerssen. +Cube game engine source code, 20 dec 2003 release. Copyright (C) 2001-2003 +Wouter van Oortmerssen. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the diff --git a/options/license/DSDP b/options/license/DSDP index f98358f04b..e790666828 100644 --- a/options/license/DSDP +++ b/options/license/DSDP @@ -1,6 +1,4 @@ -COPYRIGHT NOTIFICATION - -(C) COPYRIGHT 2004 UNIVERSITY OF CHICAGO +COPYRIGHT NOTIFICATION (C) COPYRIGHT 2004 UNIVERSITY OF CHICAGO This program discloses material protectable under copyright laws of the United States. Permission to copy and modify this software and its documentation diff --git a/options/license/EUDatagrid b/options/license/EUDatagrid index b523c5afca..f9edeac751 100644 --- a/options/license/EUDatagrid +++ b/options/license/EUDatagrid @@ -1,6 +1,4 @@ -EU DataGrid Software License - -Copyright (c) 2001 EU DataGrid. All rights reserved. +EU DataGrid Software License Copyright (c) 2001 EU DataGrid. All rights reserved. This software includes voluntary contributions made to the EU DataGrid. For more information on the EU DataGrid, please see http://www.eu-datagrid.org/. diff --git a/options/license/EUPL-1.0 b/options/license/EUPL-1.0 index 5fc85d56c4..09d08e3f03 100644 --- a/options/license/EUPL-1.0 +++ b/options/license/EUPL-1.0 @@ -1,10 +1,9 @@ -European Union Public Licence V.1.0 - -EUPL (c) the European Community 2007 This European Union Public Licence (the -"EUPL") applies to the Work or Software (as defined below) which is provided -under the terms of this Licence. Any use of the Work, other than as authorised -under this Licence is prohibited (to the extent such use is covered by a right -of the copyright holder of the Work). +European Union Public Licence V.1.0 EUPL (c) the European Community 2007 This +European Union Public Licence (the "EUPL") applies to the Work or Software +(as defined below) which is provided under the terms of this Licence. Any +use of the Work, other than as authorised under this Licence is prohibited +(to the extent such use is covered by a right of the copyright holder of the +Work). The Original Work is provided under the terms of this Licence when the Licensor (as defined below) has placed the following notice immediately following the diff --git a/options/license/EUPL-1.1 b/options/license/EUPL-1.1 index 8232c91cbc..86c834ae5b 100644 --- a/options/license/EUPL-1.1 +++ b/options/license/EUPL-1.1 @@ -1,6 +1,4 @@ -European Union Public Licence V. 1.1 - -EUPL (c) the European Community 2007 +European Union Public Licence V. 1.1 EUPL (c) the European Community 2007 This European Union Public Licence (the "EUPL") applies to the Work or Software (as defined below) which is provided under the terms of this Licence. Any diff --git a/options/license/Entessa b/options/license/Entessa index ab7172b452..a41b7a39c2 100644 --- a/options/license/Entessa +++ b/options/license/Entessa @@ -1,6 +1,5 @@ -Entessa Public License Version. 1.0 - -Copyright (c) 2003 Entessa, LLC. All rights reserved. +Entessa Public License Version. 1.0 Copyright (c) 2003 Entessa, LLC. All rights +reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/options/license/Fair b/options/license/Fair index 0bcc8c7828..9642931122 100644 --- a/options/license/Fair +++ b/options/license/Fair @@ -1,6 +1,4 @@ -Fair License - - +Fair License Usage of the works is permitted provided that this instrument is retained with the works, so that any entity that uses the works is notified of this diff --git a/options/license/GFDL-1.3-only b/options/license/GFDL-1.3-only index 506b043ecf..90f814dea7 100644 --- a/options/license/GFDL-1.3-only +++ b/options/license/GFDL-1.3-only @@ -1,9 +1,7 @@ GNU Free Documentation License -Version 1.3, 3 November 2008 - -Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. - +Version 1.3, 3 November 2008 Copyright (C) 2000, 2001, 2002, 2007, 2008 Free +Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. diff --git a/options/license/GFDL-1.3-or-later b/options/license/GFDL-1.3-or-later index 8de52f8d94..1edf769ac0 100644 --- a/options/license/GFDL-1.3-or-later +++ b/options/license/GFDL-1.3-or-later @@ -1,9 +1,7 @@ GNU Free Documentation License -Version 1.3, 3 November 2008 - -Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. - +Version 1.3, 3 November 2008 Copyright (C) 2000, 2001, 2002, 2007, 2008 Free +Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. diff --git a/options/license/GL2PS b/options/license/GL2PS index 617531b1b8..2da34219ce 100644 --- a/options/license/GL2PS +++ b/options/license/GL2PS @@ -1,6 +1,4 @@ -GL2PS LICENSE Version 2, November 2003 - -Copyright (C) 2003, Christophe Geuzaine +GL2PS LICENSE Version 2, November 2003 Copyright (C) 2003, Christophe Geuzaine Permission to use, copy, and distribute this software and its documentation for any purpose with or without fee is hereby granted, provided that the copyright diff --git a/options/license/GPL-2.0-only b/options/license/GPL-2.0-only index 4f27167ff9..0f3d6411da 100644 --- a/options/license/GPL-2.0-only +++ b/options/license/GPL-2.0-only @@ -4,7 +4,7 @@ Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 , USA +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -272,9 +272,9 @@ them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. -< one line to give the program's name and an idea of what it does. > + -Copyright (C) < yyyy > < name of author > +Copyright (C)< yyyy> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -287,7 +287,7 @@ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin -Street, Fifth Floor, Boston, MA 02110-1301 , USA. +Street, Fifth Floor, Boston, MA 02110-1301, USA. Also add information on how to contact you by electronic and paper mail. @@ -311,7 +311,7 @@ is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. -< signature of Ty Coon > , 1 April 1989 Ty Coon, President of Vice This General +, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this diff --git a/options/license/GPL-2.0-or-later b/options/license/GPL-2.0-or-later index ff0839844a..1d80ac3653 100644 --- a/options/license/GPL-2.0-or-later +++ b/options/license/GPL-2.0-or-later @@ -4,7 +4,7 @@ Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 , USA +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -287,7 +287,7 @@ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin -Street, Fifth Floor, Boston, MA 02110-1301 , USA. +Street, Fifth Floor, Boston, MA 02110-1301, USA. Also add information on how to contact you by electronic and paper mail. @@ -311,7 +311,7 @@ is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. -< signature of Ty Coon > , 1 April 1989 Ty Coon, President of Vice This General +, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this diff --git a/options/license/GPL-3.0-only b/options/license/GPL-3.0-only index 80150269e6..e142a525bd 100644 --- a/options/license/GPL-3.0-only +++ b/options/license/GPL-3.0-only @@ -2,7 +2,7 @@ GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 -Copyright © 2007 Free Software Foundation, Inc. +Copyright © 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -595,7 +595,7 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with -this program. If not, see . +this program. If not, see . Also add information on how to contact you by electronic and paper mail. @@ -615,12 +615,11 @@ be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For -more information on this, and how to apply and follow the GNU GPL, see . +more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public -License instead of this License. But first, please read . diff --git a/options/license/GPL-3.0-or-later b/options/license/GPL-3.0-or-later index 80150269e6..e142a525bd 100644 --- a/options/license/GPL-3.0-or-later +++ b/options/license/GPL-3.0-or-later @@ -2,7 +2,7 @@ GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 -Copyright © 2007 Free Software Foundation, Inc. +Copyright © 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -595,7 +595,7 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with -this program. If not, see . +this program. If not, see . Also add information on how to contact you by electronic and paper mail. @@ -615,12 +615,11 @@ be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For -more information on this, and how to apply and follow the GNU GPL, see . +more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public -License instead of this License. But first, please read . diff --git a/options/license/HPND b/options/license/HPND index d4842684d4..4662ba23b2 100644 --- a/options/license/HPND +++ b/options/license/HPND @@ -1,10 +1,8 @@ -Historical Permission Notice and Disclaimer - - +Historical Permission Notice and Disclaimer Permission to use, copy, modify and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above -copyright notice appear in all copies , and that both that the copyright notice +copyright notice appear in all copies, and that both that the copyright notice and this permission notice appear in supporting documentation , and that the name of not be used in advertising or publicity pertaining to distribution of the software without specific, diff --git a/options/license/ICU b/options/license/ICU index fabfb63664..33bac34223 100644 --- a/options/license/ICU +++ b/options/license/ICU @@ -1,8 +1,7 @@ ICU License - ICU 1.8.1 and later -COPYRIGHT AND PERMISSION NOTICE - -Copyright (c) 1995-2014 International Business Machines Corporation and others +COPYRIGHT AND PERMISSION NOTICE Copyright (c) 1995-2014 International Business +Machines Corporation and others All rights reserved. diff --git a/options/license/ISC b/options/license/ISC index 5129d95123..412d4e203d 100644 --- a/options/license/ISC +++ b/options/license/ISC @@ -1,6 +1,4 @@ -ISC License - -Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC") +ISC License Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC") Copyright (c) 1995-2003 by Internet Software Consortium diff --git a/options/license/ImageMagick b/options/license/ImageMagick index e924232f61..ea22466116 100644 --- a/options/license/ImageMagick +++ b/options/license/ImageMagick @@ -64,10 +64,9 @@ you need to acknowledge the use of the ImageMagick software; Terms and Conditions for Use, Reproduction, and Distribution The legally binding and authoritative terms and conditions for use, reproduction, -and distribution of ImageMagick follow: - -Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization dedicated -to making software imaging solutions freely available. +and distribution of ImageMagick follow: Copyright 1999-2013 ImageMagick Studio +LLC, a non-profit organization dedicated to making software imaging solutions +freely available. 1. Definitions. diff --git a/options/license/Info-ZIP b/options/license/Info-ZIP index f71109fc7a..066343e622 100644 --- a/options/license/Info-ZIP +++ b/options/license/Info-ZIP @@ -1,6 +1,4 @@ -Info-ZIP License - -Copyright (c) 1990-2009 Info-ZIP. All rights reserved. +Info-ZIP License Copyright (c) 1990-2009 Info-ZIP. All rights reserved. For the purposes of this copyright and license, "Info-ZIP" is defined as the following set of individuals: diff --git a/options/license/Intel b/options/license/Intel index 16e8341896..c719c9bcec 100644 --- a/options/license/Intel +++ b/options/license/Intel @@ -1,6 +1,4 @@ -Intel Open Source License - -Copyright (c) 1996-2000 Intel Corporation +Intel Open Source License Copyright (c) 1996-2000 Intel Corporation All rights reserved. diff --git a/options/license/Interbase-1.0 b/options/license/Interbase-1.0 index e3f76e33e8..03bdf2ffd5 100644 --- a/options/license/Interbase-1.0 +++ b/options/license/Interbase-1.0 @@ -429,7 +429,7 @@ in Exhibit A. EXHIBIT A - InterBase Public License. -" The contents of this file are subject to the Interbase Public License Version +"The contents of this file are subject to the Interbase Public License Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.Interbase.com/IPL.html diff --git a/options/license/JSON b/options/license/JSON index a2f5629de4..05a38f55cd 100644 --- a/options/license/JSON +++ b/options/license/JSON @@ -1,6 +1,4 @@ -JSON License - -Copyright (c) 2002 JSON.org +JSON License Copyright (c) 2002 JSON.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/options/license/JasPer-2.0 b/options/license/JasPer-2.0 index db2a440462..f66b353401 100644 --- a/options/license/JasPer-2.0 +++ b/options/license/JasPer-2.0 @@ -1,6 +1,4 @@ -JasPer License Version 2.0 - -Copyright (c) 2001-2006 Michael David Adams +JasPer License Version 2.0 Copyright (c) 2001-2006 Michael David Adams Copyright (c) 1999-2000 Image Power, Inc. diff --git a/options/license/LAL-1.3 b/options/license/LAL-1.3 index 57a6d46964..4dcefed47f 100644 --- a/options/license/LAL-1.3 +++ b/options/license/LAL-1.3 @@ -1,6 +1,6 @@ Licence Art Libre 1.3 (LAL 1.3) -Préambule : +Préambule : Avec la Licence Art Libre, l'autorisation est donnée de copier, de diffuser et de transformer librement les œuvres dans le respect des droits de l'auteur. @@ -12,44 +12,44 @@ d'expression. Si, en règle générale, l'application du droit d'auteur conduit à restreindre l'accès aux œuvres de l'esprit, la Licence Art Libre, au contraire, le favorise. -L'intention est d'autoriser l'utilisation des ressources d'une œuvre ; créer +L'intention est d'autoriser l'utilisation des ressources d'une œuvre ; créer de nouvelles conditions de création pour amplifier les possibilités de création. La Licence Art Libre permet d'avoir jouissance des œuvres tout en reconnaissant les droits et les responsabilités de chacun. Avec le développement du numérique, l'invention d'internet et des logiciels -libres, les modalités de création ont évolué : les productions de l'esprit +libres, les modalités de création ont évolué : les productions de l'esprit s'offrent naturellement à la circulation, à l'échange et aux transformations. Elles se prêtent favorablement à la réalisation d'œuvres communes que chacun peut augmenter pour l'avantage de tous. -C'est la raison essentielle de la Licence Art Libre : promouvoir et protéger -ces productions de l'esprit selon les principes du copyleft : liberté d'usage, +C'est la raison essentielle de la Licence Art Libre : promouvoir et protéger +ces productions de l'esprit selon les principes du copyleft : liberté d'usage, de copie, de diffusion, de transformation et interdiction d'appropriation exclusive. -Définitions : +Définitions : -Nous désignons par « œuvre », autant l'œuvre initiale, les œuvres conséquentes, -que l'œuvre commune telles que définies ci-après : +Nous désignons par « œuvre », autant l'œuvre initiale, les œuvres conséquentes, +que l'œuvre commune telles que définies ci-après : -L'œuvre commune : Il s'agit d'une œuvre qui comprend l'œuvre initiale ainsi +L'œuvre commune : Il s'agit d'une œuvre qui comprend l'œuvre initiale ainsi que toutes les contributions postérieures (les originaux conséquents et les copies). Elle est créée à l'initiative de l'auteur initial qui par cette licence définit les conditions selon lesquelles les contributions sont faites. -L'œuvre initiale : C'est-à-dire l'œuvre créée par l'initiateur de l'œuvre +L'œuvre initiale : C'est-à-dire l'œuvre créée par l'initiateur de l'œuvre commune dont les copies vont être modifiées par qui le souhaite. -Les œuvres conséquentes : C'est-à-dire les contributions des auteurs qui participent +Les œuvres conséquentes : C'est-à-dire les contributions des auteurs qui participent à la formation de l'œuvre commune en faisant usage des droits de reproduction, de diffusion et de modification que leur confère la licence. -Originaux (sources ou ressources de l'œuvre) : Chaque exemplaire daté de l'œuvre +Originaux (sources ou ressources de l'œuvre) : Chaque exemplaire daté de l'œuvre initiale ou conséquente que leurs auteurs présentent comme référence pour toutes actualisations, interprétations, copies ou reproductions ultérieures. -Copie : Toute reproduction d'un original au sens de cette licence. +Copie : Toute reproduction d'un original au sens de cette licence. 1- OBJET. @@ -70,33 +70,30 @@ personne, quelle que soit la technique employée. Vous pouvez diffuser librement les copies de ces œuvres, modifiées ou non, quel que soit le support, quel que soit le lieu, à titre onéreux ou gratuit, -si vous respectez toutes les conditions suivantes : +si vous respectez toutes les conditions suivantes : 1. joindre aux copies cette licence à l'identique ou indiquer précisément -où se trouve la licence ; +où se trouve la licence ; 2. indiquer au destinataire le nom de chaque auteur des originaux, y compris -le vôtre si vous avez modifié l'œuvre ; +le vôtre si vous avez modifié l'œuvre ; 3. indiquer au destinataire où il pourrait avoir accès aux originaux (initiaux -et/ou conséquents). - -Les auteurs des originaux pourront, s'ils le souhaitent, vous autoriser à -diffuser l'original dans les mêmes conditions que les copies. +et/ou conséquents). Les auteurs des originaux pourront, s'ils le souhaitent, +vous autoriser à diffuser l'original dans les mêmes conditions que les copies. 2.3 LA LIBERTÉ DE MODIFIER. Vous avez la liberté de modifier les copies des originaux (initiaux et conséquents) -dans le respect des conditions suivantes : +dans le respect des conditions suivantes : -1. celles prévues à l'article 2.2 en cas de diffusion de la copie modifiée -; +1. celles prévues à l'article 2.2 en cas de diffusion de la copie modifiée ; 2. indiquer qu'il s'agit d'une œuvre modifiée et, si possible, la nature de -la modification ; +la modification ; 3. diffuser cette œuvre conséquente avec la même licence ou avec toute licence -compatible ; +compatible ; 4. Les auteurs des originaux pourront, s'ils le souhaitent, vous autoriser à modifier l'original dans les mêmes conditions que les copies. @@ -104,11 +101,12 @@ compatible ; 3. DROITS CONNEXES. Les actes donnant lieu à des droits d'auteur ou des droits voisins ne doivent -pas constituer un obstacle aux libertés conférées par cette licence. C'est -pourquoi, par exemple, les interprétations doivent être soumises à la même -licence ou une licence compatible. De même, l'intégration de l'œuvre à une -base de données, une compilation ou une anthologie ne doit pas faire obstacle -à la jouissance de l'œuvre telle que définie par cette licence. +pas constituer un obstacle aux libertés conférées par cette licence. + +C'est pourquoi, par exemple, les interprétations doivent être soumises à la +même licence ou une licence compatible. De même, l'intégration de l'œuvre +à une base de données, une compilation ou une anthologie ne doit pas faire +obstacle à la jouissance de l'œuvre telle que définie par cette licence. 4. L' INTÉGRATION DE L'ŒUVRE. @@ -121,16 +119,16 @@ compatible. 5. CRITÈRES DE COMPATIBILITÉ. - Une licence est compatible avec la LAL si et seulement si : + Une licence est compatible avec la LAL si et seulement si : 1. elle accorde l'autorisation de copier, diffuser et modifier des copies de l'œuvre, y compris à des fins lucratives, et sans autres restrictions que -celles qu'impose le respect des autres critères de compatibilité ; +celles qu'impose le respect des autres critères de compatibilité ; 2. elle garantit la paternité de l'œuvre et l'accès aux versions antérieures -de l'œuvre quand cet accès est possible ; +de l'œuvre quand cet accès est possible ; - 3. elle reconnaît la LAL également compatible (réciprocité) ; + 3. elle reconnaît la LAL également compatible (réciprocité) ; 4. elle impose que les modifications faites sur l'œuvre soient soumises à la même licence ou encore à une licence répondant aux critères de compatibilité diff --git a/options/license/LGPL-2.0-only b/options/license/LGPL-2.0-only index e0419f241d..5c96471aaf 100644 --- a/options/license/LGPL-2.0-only +++ b/options/license/LGPL-2.0-only @@ -1,8 +1,6 @@ GNU LIBRARY GENERAL PUBLIC LICENSE -Version 2, June 1991 - -Copyright (C) 1991 Free Software Foundation, Inc. +Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA diff --git a/options/license/LGPL-2.0-or-later b/options/license/LGPL-2.0-or-later index e0419f241d..5c96471aaf 100644 --- a/options/license/LGPL-2.0-or-later +++ b/options/license/LGPL-2.0-or-later @@ -1,8 +1,6 @@ GNU LIBRARY GENERAL PUBLIC LICENSE -Version 2, June 1991 - -Copyright (C) 1991 Free Software Foundation, Inc. +Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA diff --git a/options/license/LGPL-3.0-only b/options/license/LGPL-3.0-only index 1344add25d..bd405afbef 100644 --- a/options/license/LGPL-3.0-only +++ b/options/license/LGPL-3.0-only @@ -2,7 +2,7 @@ GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 -Copyright (C) 2007 Free Software Foundation, Inc. +Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. diff --git a/options/license/LGPL-3.0-or-later b/options/license/LGPL-3.0-or-later index 1344add25d..bd405afbef 100644 --- a/options/license/LGPL-3.0-or-later +++ b/options/license/LGPL-3.0-or-later @@ -2,7 +2,7 @@ GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 -Copyright (C) 2007 Free Software Foundation, Inc. +Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. diff --git a/options/license/LPPL-1.0 b/options/license/LPPL-1.0 index 548004d7f8..458f89e867 100644 --- a/options/license/LPPL-1.0 +++ b/options/license/LPPL-1.0 @@ -1,8 +1,6 @@ LaTeX Project Public License -LPPL Version 1.0 1999-03-01 - -Copyright 1999 LaTeX3 Project +LPPL Version 1.0 1999-03-01 Copyright 1999 LaTeX3 Project Everyone is permitted to copy and distribute verbatim copies of this license document, but modification is not allowed. diff --git a/options/license/LPPL-1.1 b/options/license/LPPL-1.1 index 07c59e515d..0f408cb958 100644 --- a/options/license/LPPL-1.1 +++ b/options/license/LPPL-1.1 @@ -2,9 +2,7 @@ The LaTeX Project Public License =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -LPPL Version 1.1 1999-07-10 - -Copyright 1999 LaTeX3 Project +LPPL Version 1.1 1999-07-10 Copyright 1999 LaTeX3 Project Everyone is allowed to distribute verbatim copies of this license document, but modification of it is not allowed. diff --git a/options/license/LPPL-1.2 b/options/license/LPPL-1.2 index 69dbd010ab..1bb8d0db47 100644 --- a/options/license/LPPL-1.2 +++ b/options/license/LPPL-1.2 @@ -2,9 +2,7 @@ The LaTeX Project Public License =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -LPPL Version 1.2 1999-09-03 - -Copyright 1999 LaTeX3 Project +LPPL Version 1.2 1999-09-03 Copyright 1999 LaTeX3 Project Everyone is allowed to distribute verbatim copies of this license document, but modification of it is not allowed. diff --git a/options/license/LPPL-1.3a b/options/license/LPPL-1.3a index c1da143b81..2e4e567fcb 100644 --- a/options/license/LPPL-1.3a +++ b/options/license/LPPL-1.3a @@ -2,9 +2,7 @@ The LaTeX Project Public License =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -LPPL Version 1.3a 2004-10-01 - -Copyright 1999 2002-04 LaTeX3 Project +LPPL Version 1.3a 2004-10-01 Copyright 1999 2002-04 LaTeX3 Project Everyone is allowed to distribute verbatim copies of this license document, but modification of it is not allowed. diff --git a/options/license/LPPL-1.3c b/options/license/LPPL-1.3c index f05aedf9fb..b62e36895f 100644 --- a/options/license/LPPL-1.3c +++ b/options/license/LPPL-1.3c @@ -2,9 +2,7 @@ The LaTeX Project Public License =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -LPPL Version 1.3c 2008-05-04 - -Copyright 1999 2002-2008 LaTeX3 Project +LPPL Version 1.3c 2008-05-04 Copyright 1999 2002-2008 LaTeX3 Project Everyone is allowed to distribute verbatim copies of this license document, but modification of it is not allowed. diff --git a/options/license/MIT b/options/license/MIT index d449d3e548..204b93da48 100644 --- a/options/license/MIT +++ b/options/license/MIT @@ -1,6 +1,4 @@ -MIT License - -Copyright (c) +MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/options/license/MIT-CMU b/options/license/MIT-CMU index 87cc4395fa..81c351b2ef 100644 --- a/options/license/MIT-CMU +++ b/options/license/MIT-CMU @@ -1,22 +1,17 @@ -Copyright 1989, 1991, 1992 by Carnegie Mellon University + By obtaining, using, and/or copying this software and/or +its associated documentation, you agree that you have read, understood, and +will comply with the following terms and conditions: -Derivative Work - 1996, 1998-2000 Copyright 1996, 1998-2000 The Regents of -the University of California +Permission to use, copy, modify, and distribute this software and its associated +documentation for any purpose and without fee is hereby granted, provided +that the above copyright notice appears in all copies, and that both that +copyright notice and this permission notice appear in supporting documentation, +and that the name of the copyright holder not be used in advertising or publicity +pertaining to distribution of the software without specific, written permission. -All Rights Reserved - -Permission to use, copy, modify and distribute this software and its documentation -for any purpose and without fee is hereby granted, provided that the above -copyright notice appears in all copies and that both that copyright notice -and this permission notice appear in supporting documentation, and that the -name of CMU and The Regents of the University of California not be used in -advertising or publicity pertaining to distribution of the software without -specific written permission. - -CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS. IN NO EVENT SHALL CMU OR THE REGENTS OF THE UNIVERSITY OF CALIFORNIA -BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +THE COPYRIGHT HOLDER DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT +SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM THE LOSS OF USE, DATA OR +PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/options/license/MPL-1.0 b/options/license/MPL-1.0 index 0ebc564552..965a50b512 100644 --- a/options/license/MPL-1.0 +++ b/options/license/MPL-1.0 @@ -319,7 +319,7 @@ of Covered Code you made available, the revenues you received from utilizing such rights, and other relevant factors. You agree to work with affected parties to distribute responsibility on an equitable basis. EXHIBIT A. -" The contents of this file are subject to the Mozilla Public License Version +"The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ @@ -329,4 +329,4 @@ the specific language governing rights and limitations under the License. The Original Code is _____ . The Initial Developer of the Original Code is _____ . Portions created by _____ are Copyright (C) _____ . All Rights Reserved. -Contributor(s): _____ . " +Contributor(s): _____ ." diff --git a/options/license/MPL-1.1 b/options/license/MPL-1.1 index 35f0951b9d..b45d0e15ff 100644 --- a/options/license/MPL-1.1 +++ b/options/license/MPL-1.1 @@ -389,7 +389,7 @@ portions of the Covered Code under Your choice of the MPL or the alternative licenses, if any, specified by the Initial Developer in the file described in Exhibit A. Exhibit A - Mozilla Public License. -" The contents of this file are subject to the Mozilla Public License Version +"The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ @@ -414,7 +414,7 @@ to allow others to use your version of this file under the MPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the [___] License. If you do not delete the provisions above, a recipient may use your version of this file under either -the MPL or the [___] License. " +the MPL or the [___] License." NOTE: The text of this Exhibit A may differ slightly from the text of the notices in the Source Code files of the Original Code. You should use the diff --git a/options/license/MTLL b/options/license/MTLL index 90bc71ed29..a80e517285 100644 --- a/options/license/MTLL +++ b/options/license/MTLL @@ -1,6 +1,4 @@ -Software License for MTL - -Copyright (c) 2007 The Trustees of Indiana University. +Software License for MTL Copyright (c) 2007 The Trustees of Indiana University. 2008 Dresden University of Technology and the Trustees of Indiana University. diff --git a/options/license/MakeIndex b/options/license/MakeIndex index 52e1572813..e92f97685a 100644 --- a/options/license/MakeIndex +++ b/options/license/MakeIndex @@ -1,8 +1,6 @@ MakeIndex Distribution Notice -11/11/1989 - -Copyright (C) 1989 by Chen & Harrison International Systems, Inc. +11/11/1989 Copyright (C) 1989 by Chen & Harrison International Systems, Inc. Copyright (C) 1988 by Olivetti Research Center diff --git a/options/license/MirOS b/options/license/MirOS index dbb77b8a35..3fbbab0f11 100644 --- a/options/license/MirOS +++ b/options/license/MirOS @@ -1,8 +1,4 @@ -MirOS License - -Copyright [YEAR] - -[NAME] [EMAIL] +The MirOS Licence Copyright [YEAR] [NAME] [EMAIL] Provided that these terms and disclaimer and all copyright notices are retained or reproduced in an accompanying document, permission is granted to deal in @@ -15,50 +11,4 @@ intent or gross negligence. In no event may a licensor, author or contributor be held liable for indirect, direct, other damage, loss, or other issues arising in any way out of dealing in the work, even if advised of the possibility of such damage or existence of a defect, except proven that it results out -of said person's immediate fault when using the work as intended. I_N_S_T_R_U_C_T_I_O_N_S_:_ - -To apply the template(1) specify the years of copyright (separated by comma, -not as a range), the legal names of the copyright holders, and the real names -of the authors if different. Avoid adding text. - -R_A_T_I_O_N_A_L_E_:_ - -This licence is apt for any kind of work (such as source code, fonts, documentation, -graphics, sound etc.) and the preferred terms for work added to MirBSD. It -has been drafted as universally usable equivalent of the "historic permission -notice"(2) adapted to Europen law because in some (droit d'auteur) countries -authors cannot disclaim all liabi‐ lities. Compliance to DFSG(3) 1.1 is ensured, -and GPLv2 compatibility is asserted unless advertising clauses are used. The -MirOS Licence is certified to conform to OKD(4) 1.0 and OSD(5) 1.9, and qualifies -as a Free Software(6) and also Free Documentation(7) licence and is included -in some relevant lists(8)(9)(10). - -We believe you are not liable for work inserted which is intellectual property -of third parties, if you were not aware of the fact, act appropriately as -soon as you become aware of that problem, seek an amicable solution for all -parties, and never knowingly distribute a work without being authorised to -do so by its licensors. - -R_E_F_E_R_E_N_C_E_S_:_ - - - - (1) also at http://mirbsd.de/MirOS-Licence - - (2) http://www.opensource.org/licenses/historical.php - - (3) http://www.debian.org/social_contract#guidelines - - (4) http://www.opendefinition.org/1.0 - - (5) http://www.opensource.org/docs/osd - - (6) http://www.gnu.org/philosophy/free-sw.html - - (7) http://www.gnu.org/philosophy/free-doc.html - - (8) http://www.ifross.de/ifross_html/lizenzcenter.html - - (9) http://www.opendefinition.org/licenses - - (10) http://opensource.org/licenses/miros.html +of said person's immediate fault when using the work as intended. diff --git a/options/license/Multics b/options/license/Multics index 1aafc27e3b..3c99e77813 100644 --- a/options/license/Multics +++ b/options/license/Multics @@ -23,10 +23,9 @@ copyright notice and historical background appear in all copies and that both the copyright notice and historical background and this permission notice appear in supporting documentation, and that the names of MIT, HIS, BULL or BULL HN not be used in advertising or publicity pertaining to distribution -of the programs without specific prior written permission. - -Copyright 1972 by Massachusetts Institute of Technology and Honeywell Information -Systems Inc. +of the programs without specific prior written permission. Copyright 1972 +by Massachusetts Institute of Technology and Honeywell Information Systems +Inc. Copyright 2006 by BULL HN Information Systems Inc. diff --git a/options/license/NBPL-1.0 b/options/license/NBPL-1.0 index 1a0e965f48..0f59ea20de 100644 --- a/options/license/NBPL-1.0 +++ b/options/license/NBPL-1.0 @@ -1,9 +1,8 @@ -The Net Boolean Public License - -Version 1, 22 August 1998 Copyright 1998, Net Boolean Incorporated, Redwood -City, California, USA All Rights Reserved. Note: This license is derived from -the "Artistic License" as distributed with the Perl Programming Language. -Its terms are different from those of the "Artistic License." +The Net Boolean Public License Version 1, 22 August 1998 Copyright 1998, Net +Boolean Incorporated, Redwood City, California, USA All Rights Reserved. Note: +This license is derived from the "Artistic License" as distributed with the +Perl Programming Language. Its terms are different from those of the "Artistic +License." PREAMBLE diff --git a/options/license/NCSA b/options/license/NCSA index 13109f547d..3ed0f0e280 100644 --- a/options/license/NCSA +++ b/options/license/NCSA @@ -1,6 +1,5 @@ -University of Illinois/NCSA Open Source License - -Copyright (c) . All rights reserved. +University of Illinois/NCSA Open Source License Copyright (c) . All rights reserved. Developed by: diff --git a/options/license/NGPL b/options/license/NGPL index 369781ae88..7ff93a0a88 100644 --- a/options/license/NGPL +++ b/options/license/NGPL @@ -1,6 +1,4 @@ -NETHACK GENERAL PUBLIC LICENSE - -(Copyright 1989 M. Stephenson) +NETHACK GENERAL PUBLIC LICENSE (Copyright 1989 M. Stephenson) (Based on the BISON general public license, copyright 1988 Richard M. Stallman) diff --git a/options/license/NTP b/options/license/NTP index 8f4a8f0cef..8a3879bb94 100644 --- a/options/license/NTP +++ b/options/license/NTP @@ -1,6 +1,5 @@ -NTP License (NTP) - -Copyright (c) (CopyrightHoldersName) (From 4-digit-year)-(To 4-digit-year) +NTP License (NTP) Copyright (c) (CopyrightHoldersName) (From 4-digit-year)-(To +4-digit-year) Permission to use, copy, modify, and distribute this software and its documentation for any purpose with or without fee is hereby granted, provided that the above diff --git a/options/license/Naumen b/options/license/Naumen index 0a8c6e6b12..af967ef83d 100644 --- a/options/license/Naumen +++ b/options/license/Naumen @@ -1,6 +1,5 @@ -NAUMEN Public License - -This software is Copyright (c) NAUMEN (tm) and Contributors. All rights reserved. +NAUMEN Public License This software is Copyright (c) NAUMEN (tm) and Contributors. +All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/options/license/Net-SNMP b/options/license/Net-SNMP index 971630832f..f68b3cdf2c 100644 --- a/options/license/Net-SNMP +++ b/options/license/Net-SNMP @@ -1,6 +1,5 @@ ----- Part 1: CMU/UCD copyright notice: (BSD like) ----- - -Copyright 1989, 1991, 1992 by Carnegie Mellon University +---- Part 1: CMU/UCD copyright notice: (BSD like) ----- Copyright 1989, 1991, +1992 by Carnegie Mellon University Derivative Work - 1996, 1998-2000 Copyright 1996, 1998-2000 The Regents of the University of California @@ -79,10 +78,9 @@ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ----- Part 4: Sun Microsystems, Inc. copyright notice (BSD) ----- - -Copyright © 2003 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, -California 95054, U.S.A. All rights reserved. +---- Part 4: Sun Microsystems, Inc. copyright notice (BSD) ----- Copyright +© 2003 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, California +95054, U.S.A. All rights reserved. Use is subject to license terms below. @@ -174,7 +172,6 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---- Part 7: Fabasoft R&D Software GmbH & Co KG copyright notice (BSD) ----- - Copyright (c) Fabasoft R&D Software GmbH & Co KG, 2003 oss@fabasoft.com Author: Bernhard Penz @@ -203,9 +200,8 @@ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ----- Part 8: Apple Inc. copyright notice (BSD) ----- - -Copyright (c) 2007 Apple Inc. All rights reserved. +---- Part 8: Apple Inc. copyright notice (BSD) ----- Copyright (c) 2007 Apple +Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/options/license/OCLC-2.0 b/options/license/OCLC-2.0 index e4b6235d41..09cc2867bd 100644 --- a/options/license/OCLC-2.0 +++ b/options/license/OCLC-2.0 @@ -2,9 +2,8 @@ OCLC Research Public License 2.0 Terms & Conditions Of Use -May, 2002 - -Copyright © 2002. OCLC Online Computer Library Center, Inc. All Rights Reserved +May, 2002 Copyright © 2002. OCLC Online Computer Library Center, Inc. All +Rights Reserved PLEASE READ THIS DOCUMENT CAREFULLY. BY DOWNLOADING OR USING THE CODE BASE AND/OR DOCUMENTATION ACCOMPANYING THIS LICENSE (THE "License"), YOU AGREE @@ -79,7 +78,7 @@ If you distribute the Program in a form to which the recipient can make Modifica addition, each source and data file of the Program and any Modification you distribute must contain the following notice: -" Copyright (c) 2000- (insert then current year) OCLC Online Computer Library +"Copyright (c) 2000- (insert then current year) OCLC Online Computer Library Center, Inc. and other contributors . All rights reserved. The contents of this file, as updated from time to time by the OCLC Office of Research, are subject to OCLC Research Public License Version 2.0 (the "License"); you may @@ -93,7 +92,7 @@ OCLC Research. For more information on OCLC Research, please see http://www.oclc The Original Code is ______________________________ . The Initial Developer of the Original Code is ________________________ . Portions created by ______________________ are Copyright (C) ____________________________ . All Rights Reserved. Contributor(s): -______________________________________ . " +______________________________________ ." C. Requirements for a Distribution of Non-modifiable Code diff --git a/options/license/OLDAP-1.1 b/options/license/OLDAP-1.1 index c8a97ebeaa..522a67d775 100644 --- a/options/license/OLDAP-1.1 +++ b/options/license/OLDAP-1.1 @@ -1,10 +1,9 @@ The OpenLDAP Public License -Version 1.1, 25 August 1998 - -Copyright 1998, The OpenLDAP Foundation. All Rights Reserved. Note: This license -is derived from the "Artistic License" as distributed with the Perl Programming -Language. Its terms are different from those of the "Artistic License." +Version 1.1, 25 August 1998 Copyright 1998, The OpenLDAP Foundation. All Rights +Reserved. Note: This license is derived from the "Artistic License" as distributed +with the Perl Programming Language. Its terms are different from those of +the "Artistic License." PREAMBLE diff --git a/options/license/OLDAP-1.2 b/options/license/OLDAP-1.2 index c520e91cf0..a91e91017f 100644 --- a/options/license/OLDAP-1.2 +++ b/options/license/OLDAP-1.2 @@ -1,10 +1,9 @@ The OpenLDAP Public License -Version 1.2, 1 September 1998 - -Copyright 1998, The OpenLDAP Foundation. All Rights Reserved. Note: This license -is derived from the "Artistic License" as distributed with the Perl Programming -Language. As differences may exist, the complete license should be read. +Version 1.2, 1 September 1998 Copyright 1998, The OpenLDAP Foundation. All +Rights Reserved. Note: This license is derived from the "Artistic License" +as distributed with the Perl Programming Language. As differences may exist, +the complete license should be read. PREAMBLE diff --git a/options/license/OLDAP-1.3 b/options/license/OLDAP-1.3 index edcb2ac500..cf489a9d65 100644 --- a/options/license/OLDAP-1.3 +++ b/options/license/OLDAP-1.3 @@ -1,11 +1,9 @@ The OpenLDAP Public License -Version 1.3, 17 January 1999 - -Copyright 1998-1999, The OpenLDAP Foundation. All Rights Reserved. Note: This -license is derived from the "Artistic License" as distributed with the Perl -Programming Language. As significant differences exist, the complete license -should be read. +Version 1.3, 17 January 1999 Copyright 1998-1999, The OpenLDAP Foundation. +All Rights Reserved. Note: This license is derived from the "Artistic License" +as distributed with the Perl Programming Language. As significant differences +exist, the complete license should be read. PREAMBLE diff --git a/options/license/OLDAP-1.4 b/options/license/OLDAP-1.4 index beb9b992e9..74d8ebd902 100644 --- a/options/license/OLDAP-1.4 +++ b/options/license/OLDAP-1.4 @@ -1,11 +1,9 @@ The OpenLDAP Public License -Version 1.4, 18 January 1999 - -Copyright 1998-1999, The OpenLDAP Foundation. All Rights Reserved. Note: This -license is derived from the "Artistic License" as distributed with the Perl -Programming Language. As significant differences exist, the complete license -should be read. +Version 1.4, 18 January 1999 Copyright 1998-1999, The OpenLDAP Foundation. +All Rights Reserved. Note: This license is derived from the "Artistic License" +as distributed with the Perl Programming Language. As significant differences +exist, the complete license should be read. PREAMBLE diff --git a/options/license/OLDAP-2.0 b/options/license/OLDAP-2.0 index 1076e3eeea..7dd47ef9cc 100644 --- a/options/license/OLDAP-2.0 +++ b/options/license/OLDAP-2.0 @@ -1,9 +1,7 @@ The OpenLDAP Public License -Version 2.0, 7 June 1999 - -Copyright 1999, The OpenLDAP Foundation, Redwood City, California, USA. All -Rights Reserved. +Version 2.0, 7 June 1999 Copyright 1999, The OpenLDAP Foundation, Redwood +City, California, USA. All Rights Reserved. Redistribution and use of this software and associated documentation ("Software"), with or without modification, are permitted provided that the following conditions diff --git a/options/license/OLDAP-2.0.1 b/options/license/OLDAP-2.0.1 index f535ee22fb..5547eb18a4 100644 --- a/options/license/OLDAP-2.0.1 +++ b/options/license/OLDAP-2.0.1 @@ -1,9 +1,7 @@ The OpenLDAP Public License -Version 2.0.1, 21 December 1999 - -Copyright 1999, The OpenLDAP Foundation, Redwood City, California, USA. All -Rights Reserved. +Version 2.0.1, 21 December 1999 Copyright 1999, The OpenLDAP Foundation, Redwood +City, California, USA. All Rights Reserved. Redistribution and use of this software and associated documentation ("Software"), with or without modification, are permitted provided that the following conditions diff --git a/options/license/OLDAP-2.1 b/options/license/OLDAP-2.1 index 73beac1299..8c832b669d 100644 --- a/options/license/OLDAP-2.1 +++ b/options/license/OLDAP-2.1 @@ -1,9 +1,7 @@ The OpenLDAP Public License -Version 2.1, 29 February 2000 - -Copyright 1999-2000, The OpenLDAP Foundation, Redwood City, California, USA. -All Rights Reserved. +Version 2.1, 29 February 2000 Copyright 1999-2000, The OpenLDAP Foundation, +Redwood City, California, USA. All Rights Reserved. Redistribution and use of this software and associated documentation ("Software"), with or without modification, are permitted provided that the following conditions diff --git a/options/license/OSET-PL-2.1 b/options/license/OSET-PL-2.1 index 3f2e24aca2..fe7dd94376 100644 --- a/options/license/OSET-PL-2.1 +++ b/options/license/OSET-PL-2.1 @@ -1,9 +1,7 @@ -OSET Public License - -(c) 2015 ALL RIGHTS RESERVED VERSION 2.1 THIS LICENSE DEFINES THE RIGHTS OF -USE, REPRODUCTION, DISTRIBUTION, MODIFICATION, AND REDISTRIBUTION OF CERTAIN -COVERED SOFTWARE (AS DEFINED BELOW) ORIGINALLY RELEASED BY THE OPEN SOURCE -ELECTION TECHNOLOGY FOUNDATION (FORMERLY "THE OSDV FOUNDATION"). +OSET Public License (c) 2015 ALL RIGHTS RESERVED VERSION 2.1 THIS LICENSE +DEFINES THE RIGHTS OF USE, REPRODUCTION, DISTRIBUTION, MODIFICATION, AND REDISTRIBUTION +OF CERTAIN COVERED SOFTWARE (AS DEFINED BELOW) ORIGINALLY RELEASED BY THE +OPEN SOURCE ELECTION TECHNOLOGY FOUNDATION (FORMERLY "THE OSDV FOUNDATION"). ANYONE WHO USES, REPRODUCES, DISTRIBUTES, MODIFIES, OR REDISTRIBUTES THE COVERED SOFTWARE, OR ANY PART THEREOF, IS BY THAT ACTION, ACCEPTING IN FULL THE TERMS diff --git a/options/license/OSL-1.0 b/options/license/OSL-1.0 index 855ec6948b..0f250090ba 100644 --- a/options/license/OSL-1.0 +++ b/options/license/OSL-1.0 @@ -5,7 +5,7 @@ authorship (the "Original Work") whose owner (the "Licensor") has placed the following notice immediately following the copyright notice for the Original Work: -" Licensed under the Open Software License version 1.0 " +"Licensed under the Open Software License version 1.0" License Terms diff --git a/options/license/OpenSSL b/options/license/OpenSSL index abf6ab2960..75dee7cc28 100644 --- a/options/license/OpenSSL +++ b/options/license/OpenSSL @@ -1,6 +1,4 @@ -OpenSSL License - -Copyright (c) 1998-2008 The OpenSSL Project. All rights reserved. +OpenSSL License Copyright (c) 1998-2008 The OpenSSL Project. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -41,9 +39,7 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This product includes cryptographic software written by Eric Young (eay@cryptsoft.com). This product includes software written by Tim Hudson (tjh@cryptsoft.com). -Original SSLeay License - -Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) +Original SSLeay License Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) All rights reserved. diff --git a/options/license/PHP-3.0 b/options/license/PHP-3.0 index 4089bd5e54..a5d9221eab 100644 --- a/options/license/PHP-3.0 +++ b/options/license/PHP-3.0 @@ -1,6 +1,5 @@ -The PHP License, version 3.0 - -Copyright (c) 1999 - 2006 The PHP Group. All rights reserved. +The PHP License, version 3.0 Copyright (c) 1999 - 2006 The PHP Group. All +rights reserved. Redistribution and use in source and binary forms, with or without modification, is permitted provided that the following conditions are met: diff --git a/options/license/PHP-3.01 b/options/license/PHP-3.01 index e272ad7a85..a7147cf45c 100644 --- a/options/license/PHP-3.01 +++ b/options/license/PHP-3.01 @@ -1,6 +1,5 @@ -The PHP License, version 3.01 - -Copyright (c) 1999 - 2012 The PHP Group. All rights reserved. +The PHP License, version 3.01 Copyright (c) 1999 - 2012 The PHP Group. All +rights reserved. Redistribution and use in source and binary forms, with or without modification, is permitted provided that the following conditions are met: diff --git a/options/license/Plexus b/options/license/Plexus index b92da8329b..51c41233e2 100644 --- a/options/license/Plexus +++ b/options/license/Plexus @@ -1,4 +1,4 @@ -Copyright 2002 (C) The Codehaus . All Rights Reserved. +Copyright 2002 (C) The Codehaus. All Rights Reserved. Redistribution and use of this software and associated documentation ("Software"), with or without modification, are permitted provided that the following conditions diff --git a/options/license/PostgreSQL b/options/license/PostgreSQL index 942cf0803d..06ef3c5d29 100644 --- a/options/license/PostgreSQL +++ b/options/license/PostgreSQL @@ -1,8 +1,7 @@ PostgreSQL Database Management System -(formerly known as Postgres, then as Postgres95) - -Portions Copyright (c) 1996-2010, The PostgreSQL Global Development Group +(formerly known as Postgres, then as Postgres95) Portions Copyright (c) 1996-2010, +The PostgreSQL Global Development Group Portions Copyright (c) 1994, The Regents of the University of California diff --git a/options/license/Python-2.0 b/options/license/Python-2.0 index 1b738a6157..04962c0643 100644 --- a/options/license/Python-2.0 +++ b/options/license/Python-2.0 @@ -140,10 +140,8 @@ or any third party. 8. By clicking on the "ACCEPT" button where indicated, or by copying, installing or otherwise using Python 1.6b1, Licensee agrees to be bound by the terms and conditions of this License Agreement. ACCEPT CWI LICENSE AGREEMENT FOR -PYTHON 0.9.0 THROUGH 1.2 - -Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, The Netherlands. -All rights reserved. +PYTHON 0.9.0 THROUGH 1.2 Copyright (c) 1991 - 1995, Stichting Mathematisch +Centrum Amsterdam, The Netherlands. All rights reserved. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above diff --git a/options/license/QPL-1.0 b/options/license/QPL-1.0 index c9d1f95fe0..83e9ca42c7 100644 --- a/options/license/QPL-1.0 +++ b/options/license/QPL-1.0 @@ -1,6 +1,4 @@ -THE Q PUBLIC LICENSE version 1.0 - -Copyright (C) 1999-2005 Trolltech AS, Norway. +THE Q PUBLIC LICENSE version 1.0 Copyright (C) 1999-2005 Trolltech AS, Norway. Everyone is permitted to copy and distribute this license document. diff --git a/options/license/RPL-1.1 b/options/license/RPL-1.1 index 63c22fa1bb..c50ff79d9b 100644 --- a/options/license/RPL-1.1 +++ b/options/license/RPL-1.1 @@ -1,6 +1,5 @@ -Reciprocal Public License, version 1.1 - -Copyright (C) 2001-2002 Technical Pursuit Inc., All Rights Reserved. PREAMBLE +Reciprocal Public License, version 1.1 Copyright (C) 2001-2002 Technical Pursuit +Inc., All Rights Reserved. PREAMBLE This Preamble is intended to describe, in plain English, the nature, intent, and scope of this License. However, this Preamble is not a part of this License. diff --git a/options/license/RPSL-1.0 b/options/license/RPSL-1.0 index ad4adba76a..5318b638a9 100644 --- a/options/license/RPSL-1.0 +++ b/options/license/RPSL-1.0 @@ -416,7 +416,7 @@ and all related documents be drafted in English. Les parties ont exigé que le présent contrat et tous les documents connexes soient rédigés en anglais. EXHIBIT A. -" Copyright (c) 1995-2002 RealNetworks, Inc. and/or its licensors. All Rights +"Copyright (c) 1995-2002 RealNetworks, Inc. and/or its licensors. All Rights Reserved. The contents of this file, and the files included with this file, are subject @@ -442,7 +442,7 @@ PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Contributor(s): ____________________________________ Technology Compatibility Kit Test Suite(s) Location (if licensed under the -RCSL): _____ " +RCSL): _____" Object Code Notice: Helix DNA Client technology included. Copyright (c) RealNetworks, Inc., 1995-2002. All rights reserved. diff --git a/options/license/RSCPL b/options/license/RSCPL index 53df1bffae..dd9d1f0701 100644 --- a/options/license/RSCPL +++ b/options/license/RSCPL @@ -301,13 +301,13 @@ NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDIC DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THAT EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. TO THE EXTENT THAT ANY EXCLUSION OF DAMAGES ABOVE IS NOT VALID, YOU AGREE THAT IN NO EVENT WILL -RSV ' S LIABILITY UNDER OR RELATED TO THIS AGREEMENT EXCEED FIVE THOUSAND -DOLLARS ($5,000). THE GOVERNED CODE IS NOT INTENDED FOR USE IN CONNECTION -WITH ANY NUCLER, AVIATION, MASS TRANSIT OR MEDICAL APPLICATION OR ANY OTHER -INHERENTLY DANGEROUS APPLICATION THAT COULD RESULT IN DEATH, PERSONAL INJURY, -CATASTROPHIC DAMAGE OR MASS DESTRUCTION, AND YOU AGREE THAT NEITHER RSV NOR -ANY CONTRIBUTOR SHALL HAVE ANY LIABILITY OF ANY NATURE AS A RESULT OF ANY -SUCH USE OF THE GOVERNED CODE. +RSV'S LIABILITY UNDER OR RELATED TO THIS AGREEMENT EXCEED FIVE THOUSAND DOLLARS +($5,000). THE GOVERNED CODE IS NOT INTENDED FOR USE IN CONNECTION WITH ANY +NUCLER, AVIATION, MASS TRANSIT OR MEDICAL APPLICATION OR ANY OTHER INHERENTLY +DANGEROUS APPLICATION THAT COULD RESULT IN DEATH, PERSONAL INJURY, CATASTROPHIC +DAMAGE OR MASS DESTRUCTION, AND YOU AGREE THAT NEITHER RSV NOR ANY CONTRIBUTOR +SHALL HAVE ANY LIABILITY OF ANY NATURE AS A RESULT OF ANY SUCH USE OF THE +GOVERNED CODE. 10. U.S. Government End Users. @@ -330,7 +330,7 @@ further agree that any cause of action arising under or related to this Agreemen shall be brought in the Federal Courts of the Northern District of California, with venue lying in Santa Clara County, California. The losing party shall be responsible for costs, including without limitation, court costs and reasonable -attorney ' s fees and expenses. Notwithstanding anything to the contrary herein, +attorney's fees and expenses. Notwithstanding anything to the contrary herein, RSV may seek injunctive relief related to a breach of this Agreement in any court of competent jurisdiction. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any diff --git a/options/license/SGI-B-1.0 b/options/license/SGI-B-1.0 index 9226eeb60b..2500c0ce9d 100644 --- a/options/license/SGI-B-1.0 +++ b/options/license/SGI-B-1.0 @@ -222,11 +222,10 @@ INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND CONDITIONS OF MERCHANT SATISFACTORY QUALITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. Original Code. The Original Code is: [ name of software , version number , -and release date ] , developed by Silicon Graphics, Inc. The Original Code -is Copyright (c) [ dates of first publication, as appearing in the Notice -in the Original Code ] Silicon Graphics, Inc. Copyright in any portions created +and release date], developed by Silicon Graphics, Inc. The Original Code is +Copyright (c) [ dates of first publication, as appearing in the Notice in +the Original Code] Silicon Graphics, Inc. Copyright in any portions created by third parties is as indicated elsewhere herein. All Rights Reserved. Additional Notice Provisions: [ such additional provisions, if any, as appear -in the Notice in the Original Code under the heading "Additional Notice Provisions" -] +in the Notice in the Original Code under the heading "Additional Notice Provisions"] diff --git a/options/license/SGI-B-1.1 b/options/license/SGI-B-1.1 index 81f5770b00..8fc157b57f 100644 --- a/options/license/SGI-B-1.1 +++ b/options/license/SGI-B-1.1 @@ -238,10 +238,9 @@ INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND CONDITIONS OF MERCHANT SATISFACTORY QUALITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. Original Code. The Original Code is: [ name of software , version number , -and release date ] , developed by Silicon Graphics, Inc. The Original Code +and release date] , developed by Silicon Graphics, Inc. The Original Code is Copyright (c) [ dates of first publication, as appearing in the Notice -in the Original Code ] Silicon Graphics, Inc. Copyright in any portions created +in the Original Code] Silicon Graphics, Inc. Copyright in any portions created by third parties is as indicated elsewhere herein. All Rights Reserved. Additional Notice Provisions: [ such additional provisions, if any, as appear in the -Notice in the Original Code under the heading "Additional Notice Provisions" -] +Notice in the Original Code under the heading "Additional Notice Provisions"] diff --git a/options/license/SGI-B-2.0 b/options/license/SGI-B-2.0 index a568416505..e53cfa5438 100644 --- a/options/license/SGI-B-2.0 +++ b/options/license/SGI-B-2.0 @@ -1,9 +1,7 @@ SGI FREE SOFTWARE LICENSE B -(Version 2.0, Sept. 18, 2008) - -Copyright (C) [dates of first publication] Silicon Graphics, Inc. All Rights -Reserved. +(Version 2.0, Sept. 18, 2008) Copyright (C) [dates of first publication] Silicon +Graphics, Inc. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/options/license/SISSL b/options/license/SISSL index 1889ac0bb8..90acef9add 100644 --- a/options/license/SISSL +++ b/options/license/SISSL @@ -238,7 +238,7 @@ law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. EXHIBIT A - Sun Standards License -" The contents of this file are subject to the Sun Standards License Version +"The contents of this file are subject to the Sun Standards License Version 1.1 (the "License"); You may not use this file except in compliance with the License. You may obtain a copy of the License at _______________________________ . diff --git a/options/license/SISSL-1.2 b/options/license/SISSL-1.2 index f1e79aa013..f08ce325db 100644 --- a/options/license/SISSL-1.2 +++ b/options/license/SISSL-1.2 @@ -202,32 +202,31 @@ which have been validly granted by You or any distributor hereunder prior to termination shall survive termination. EXHIBIT A - Sun Industry Standards Source License -" The contents of this file are subject to the Sun Industry Standards Source +"The contents of this file are subject to the Sun Industry Standards Source License Version 1.2 (the License); You -may not use this file except in compliance with the License. " +may not use this file except in compliance with the License." -" You may obtain a copy of the License at gridengine.sunsource.net/license.html -" +"You may obtain a copy of the License at gridengine.sunsource.net/license.html" -" Software distributed under the License is distributed on an AS IS basis, +"Software distributed under the License is distributed on an AS IS basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations -under the License. " +under the License." -" The Original Code is Grid Engine. " +"The Original Code is Grid Engine." -" The Initial Developer of the Original Code is: +"The Initial Developer of the Original Code is: -Sun Microsystems, Inc. " +Sun Microsystems, Inc." -" Portions created by: Sun Microsystems, Inc. are Copyright (C) 2001 Sun Microsystems, -Inc. " +"Portions created by: Sun Microsystems, Inc. are Copyright (C) 2001 Sun Microsystems, +Inc." -" All Rights Reserved. " +"All Rights Reserved." -" Contributor(s): __________________________________" +"Contributor(s): __________________________________" EXHIBIT B - Standards diff --git a/options/license/SMLNJ b/options/license/SMLNJ index 5f45eb822e..307e2cc364 100644 --- a/options/license/SMLNJ +++ b/options/license/SMLNJ @@ -1,6 +1,5 @@ -STANDARD ML OF NEW JERSEY COPYRIGHT NOTICE, LICENSE AND DISCLAIMER. - -Copyright (c) 2001-2011 by The Fellowship of SML/NJ +STANDARD ML OF NEW JERSEY COPYRIGHT NOTICE, LICENSE AND DISCLAIMER. Copyright +(c) 2001-2011 by The Fellowship of SML/NJ Copyright (c) 1989-2001 by Lucent Technologies diff --git a/options/license/SMPPL b/options/license/SMPPL index c54a4ae86e..071d456412 100644 --- a/options/license/SMPPL +++ b/options/license/SMPPL @@ -58,6 +58,5 @@ The SMP uses the Enhanced SNACC (eSNACC) Abstract Syntax Notation One (ASN.1) C++ Library to ASN.1 encode and decode security-related data objects. The eSNACC ASN.1 C++ Library is covered by the ENHANCED SNACC SOFTWARE PUBLIC LICENSE. None of the GNU public licenses apply to the eSNACC ASN.1 C++ Library. -The eSNACC Compiler is not distributed as part of the SMP. - -Copyright © 1997-2002 National Security Agency +The eSNACC Compiler is not distributed as part of the SMP. Copyright © 1997-2002 +National Security Agency diff --git a/options/license/Sleepycat b/options/license/Sleepycat index 7c942ad81b..bc10a6b606 100644 --- a/options/license/Sleepycat +++ b/options/license/Sleepycat @@ -30,10 +30,8 @@ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -Copyright (c) 1990, 1993, 1994, 1995 The Regents of the University of California. -All rights reserved. +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Copyright (c) 1990, 1993, 1994, +1995 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -58,10 +56,8 @@ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -Copyright (c) 1995, 1996 The President and Fellows of Harvard University. -All rights reserved. +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Copyright (c) 1995, 1996 The President +and Fellows of Harvard University. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/options/license/TMate b/options/license/TMate index 7a7cacd8e0..69b0d82677 100644 --- a/options/license/TMate +++ b/options/license/TMate @@ -3,9 +3,8 @@ SVNKit library, which are not externally-maintained libraries (e.g. Ganymed SSH library). All the source code and compiled classes in package org.tigris.subversion.javahl -except SvnClient class are covered by the license in JAVAHL-LICENSE file - -Copyright (c) 2004-2012 TMate Software. All rights reserved. +except SvnClient class are covered by the license in JAVAHL-LICENSE file Copyright +(c) 2004-2012 TMate Software. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/options/license/TORQUE-1.1 b/options/license/TORQUE-1.1 index a4b7e0c182..f8084aa60a 100644 --- a/options/license/TORQUE-1.1 +++ b/options/license/TORQUE-1.1 @@ -1,10 +1,8 @@ -TORQUE v2.5+ Software License v1.1 - -Copyright (c) 2010-2011 Adaptive Computing Enterprises, Inc. All rights reserved. -Use this license to use or redistribute the TORQUE software v2.5+ and later -versions. For free support for TORQUE users, questions should be emailed to -the community of TORQUE users at torqueusers@supercluster.org. Users can also -subscribe to the user mailing list at http://www.supercluster.org/mailman/listinfo/torqueusers. +TORQUE v2.5+ Software License v1.1 Copyright (c) 2010-2011 Adaptive Computing +Enterprises, Inc. All rights reserved. Use this license to use or redistribute +the TORQUE software v2.5+ and later versions. For free support for TORQUE +users, questions should be emailed to the community of TORQUE users at torqueusers@supercluster.org. +Users can also subscribe to the user mailing list at http://www.supercluster.org/mailman/listinfo/torqueusers. Customers using TORQUE that also are licensed users of Moab branded software from Adaptive Computing Inc. can get TORQUE support from Adaptive Computing via: diff --git a/options/license/Unicode-DFS-2016 b/options/license/Unicode-DFS-2016 index 9cdadd9b8b..80bd8b3d8e 100644 --- a/options/license/Unicode-DFS-2016 +++ b/options/license/Unicode-DFS-2016 @@ -2,7 +2,7 @@ UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE Unicode Data Files include all data files under the directories http://www.unicode.org/Public/, http://www.unicode.org/reports/, http://www.unicode.org/cldr/data/, http://source.icu-project.org/repos/icu/, -and http://www.unicode.org/utility/trac/browser/. +http://www.unicode.org/ivd/data/, and http://www.unicode.org/utility/trac/browser/. Unicode Data Files do not include PDF online code charts under the directory http://www.unicode.org/Public/. @@ -18,10 +18,8 @@ AND/OR SOFTWARE ("SOFTWARE"), YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE. -COPYRIGHT AND PERMISSION NOTICE - -Copyright © 1991-2016 Unicode, Inc. All rights reserved. Distributed under -the Terms of Use in http://www.unicode.org/copyright.html. +COPYRIGHT AND PERMISSION NOTICE Copyright © 1991-2016 Unicode, Inc. All rights +reserved. Distributed under the Terms of Use in http://www.unicode.org/copyright.html. Permission is hereby granted, free of charge, to any person obtaining a copy of the Unicode data files and any associated documentation (the "Data Files") diff --git a/options/license/Unlicense b/options/license/Unlicense index 383d61812d..24a8f90199 100644 --- a/options/license/Unlicense +++ b/options/license/Unlicense @@ -7,17 +7,14 @@ purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and -to the detriment of our heirs and - -successors. We intend this dedication to be an overt act of relinquishment -in perpetuity of all present and future rights to this software under copyright -law. +to the detriment of our heirs and successors. We intend this dedication to +be an overt act of relinquishment in perpetuity of all present and future +rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -For more information, please refer to +THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. For more information, +please refer to diff --git a/options/license/VOSTROM b/options/license/VOSTROM index 0bf372247c..43c1c87d6a 100644 --- a/options/license/VOSTROM +++ b/options/license/VOSTROM @@ -1,6 +1,5 @@ -VOSTROM Public License for Open Source - -Copyright (c) 2007 VOSTROM Holdings, Inc. +VOSTROM Public License for Open Source Copyright (c) 2007 VOSTROM Holdings, +Inc. This VOSTROM Holdings, Inc. (VOSTROM) Distribution (code and documentation) is made available to the open source community as a public service by VOSTROM. diff --git a/options/license/VSL-1.0 b/options/license/VSL-1.0 index c0edfffe44..dd7bb74068 100644 --- a/options/license/VSL-1.0 +++ b/options/license/VSL-1.0 @@ -1,9 +1,8 @@ Vovida Software License v. 1.0 This license applies to all software incorporated in the "Vovida Open Communication Application Library" except for those portions incorporating third party software specifically identified as being licensed -under separate license. The Vovida Software License, Version 1.0 - -Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. +under separate license. The Vovida Software License, Version 1.0 Copyright +(c) 2000 Vovida Networks, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/options/license/Vim b/options/license/Vim index b3f8d0ec0f..80349f7f1f 100644 --- a/options/license/Vim +++ b/options/license/Vim @@ -2,12 +2,13 @@ VIM LICENSE I) There are no restrictions on distributing unmodified copies of Vim except that they must include this license text. You can also distribute unmodified -parts of Vim, likewise unrestricted except that they must include this license +parts of Vim , likewise unrestricted except that they must include this license text. You are also allowed to include executables that you made from the unmodified Vim sources, plus your own usage examples and Vim scripts. -II) It is allowed to distribute a modified (or extended) version of Vim, including -executables and/or source code, when the following four conditions are met: +II) It is allowed to distribute a modified (or extended) version of Vim , +including executables and/or source code, when the following four conditions +are met: 1) This license text must be included unmodified. @@ -17,7 +18,7 @@ a) If you make changes to Vim yourself, you must clearly describe in the distrib how to contact you. When the maintainer asks you (in any way) for a copy of the modified Vim you distributed, you must make your changes, including source code, available to the maintainer without fee. The maintainer reserves the -right to include your changes in the official version of Vim. What the maintainer +right to include your changes in the official version of Vim . What the maintainer will do with your changes and under what license they will be distributed is negotiable. If there has been no negotiation then this license, or a later version, also applies to your changes. The current maintainer is Bram Moolenaar @@ -35,7 +36,7 @@ c) Provide all the changes, including source code, with every copy of the modified Vim you distribute. This may be done in the form of a context diff. You can choose what license to use for new code you add. The changes and their license must not restrict others from making their own changes to the official -version of Vim. +version of Vim . d) When you have a modified Vim which includes changes as mentioned under c), you can distribute it without the source code for the changes if the following @@ -46,13 +47,13 @@ to the Vim maintainer without fee or restriction, and permits the Vim maintainer to include the changes in the official version of Vim without fee or restriction. - You keep the changes for at least three years after last distributing the -corresponding modified Vim. When the maintainer or someone who you distributed +corresponding modified Vim . When the maintainer or someone who you distributed the modified Vim to asks you (in any way) for the changes within this period, you must make them available to him. - You clearly describe in the distribution how to contact you. This contact information must remain valid for at least three years after last distributing -the corresponding modified Vim, or as long as possible. +the corresponding modified Vim , or as long as possible. e) When the GNU General Public License (GPL) applies to the changes, you can distribute the modified Vim under the GNU GPL version 2 or any later version. @@ -66,7 +67,7 @@ license used for the changes. 4) The contact information as required under 2)a) and 2)d) must not be removed or changed, except that the person himself can make corrections. -III) If you distribute a modified version of Vim, you are encouraged to use +III) If you distribute a modified version of Vim , you are encouraged to use the Vim license for your changes and make them available to the maintainer, including the source code. The preferred way to do this is by e-mail or by uploading the files to a server and e-mailing the URL. If the number of changes diff --git a/options/license/W3C-19980720 b/options/license/W3C-19980720 index 05d9b38cf0..3adf89b95f 100644 --- a/options/license/W3C-19980720 +++ b/options/license/W3C-19980720 @@ -1,8 +1,6 @@ -W3C® SOFTWARE NOTICE AND LICENSE - -Copyright (c) 1994-2002 World Wide Web Consortium, (Massachusetts Institute -of Technology, Institut National de Recherche en Informatique et en Automatique, -Keio University). All Rights Reserved. http://www.w3.org/Consortium/Legal/ +W3C® SOFTWARE NOTICE AND LICENSE Copyright (c) 1994-2002 World Wide Web Consortium, +(Massachusetts Institute of Technology, Institut National de Recherche en +Informatique et en Automatique, Keio University). All Rights Reserved. http://www.w3.org/Consortium/Legal/ This W3C work (including software, documents, or other related items) is being provided by the copyright holders under the following license. By obtaining, diff --git a/options/license/Wsuipa b/options/license/Wsuipa index f527947022..cfbd46f907 100644 --- a/options/license/Wsuipa +++ b/options/license/Wsuipa @@ -3,7 +3,6 @@ Guenther and pointers to this file were added to all source files. Unlimited copying and redistribution of each of the files is permitted as long as the file is not modified. Modifications, and redistribution of modified -versions, are also permitted, but only if the resulting file is renamed. - -The copyright holder is Washington State University. The original author of -the fonts is Janene Winter. The primary contact (as of 2008) is Dean Guenther. +versions, are also permitted, but only if the resulting file is renamed. The +copyright holder is Washington State University. The original author of the +fonts is Janene Winter. The primary contact (as of 2008) is Dean Guenther. diff --git a/options/license/X11 b/options/license/X11 index 5994ddf732..da478eb05a 100644 --- a/options/license/X11 +++ b/options/license/X11 @@ -1,6 +1,4 @@ -X11 License - -Copyright (C) 1996 X Consortium +X11 License Copyright (C) 1996 X Consortium Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/options/license/XFree86-1.1 b/options/license/XFree86-1.1 index 1b51930b57..5ba31cc2f9 100644 --- a/options/license/XFree86-1.1 +++ b/options/license/XFree86-1.1 @@ -1,6 +1,4 @@ -XFree86 License (version 1.1) - -Copyright (C) 1994-2006 The XFree86 Project, Inc. +XFree86 License (version 1.1) Copyright (C) 1994-2006 The XFree86 Project, Inc. All rights reserved. diff --git a/options/license/Xnet b/options/license/Xnet index 082ccdf980..dba87b3f80 100644 --- a/options/license/Xnet +++ b/options/license/Xnet @@ -1,6 +1,5 @@ -The X.Net, Inc. License - -Copyright (c) 2000-2001 X.Net, Inc. Lafayette, California, USA +The X.Net, Inc. License Copyright (c) 2000-2001 X.Net, Inc. Lafayette, California, +USA Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/options/license/ZPL-1.1 b/options/license/ZPL-1.1 index 6fb34ae160..43ae9e0109 100644 --- a/options/license/ZPL-1.1 +++ b/options/license/ZPL-1.1 @@ -1,7 +1,5 @@ -Zope Public License (ZPL) Version 1.1 - -Copyright (c) Zope Corporation. All rights reserved. This license has been -certified as open source. +Zope Public License (ZPL) Version 1.1 Copyright (c) Zope Corporation. All +rights reserved. This license has been certified as open source. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/options/license/ZPL-2.0 b/options/license/ZPL-2.0 index 45a4138cf7..516081c189 100644 --- a/options/license/ZPL-2.0 +++ b/options/license/ZPL-2.0 @@ -1,8 +1,7 @@ -Zope Public License (ZPL) Version 2.0 - -This software is Copyright (c) Zope Corporation (tm) and Contributors. All -rights reserved. This license has been certified as open source. It has also -been designated as GPL compatible by the Free Software Foundation (FSF). +Zope Public License (ZPL) Version 2.0 This software is Copyright (c) Zope +Corporation (tm) and Contributors. All rights reserved. This license has been +certified as open source. It has also been designated as GPL compatible by +the Free Software Foundation (FSF). Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/options/license/curl b/options/license/curl index 9c674d8c0f..c891714b1b 100644 --- a/options/license/curl +++ b/options/license/curl @@ -1,6 +1,5 @@ -COPYRIGHT AND PERMISSION NOTICE - -Copyright (c) 1996 - 2015, Daniel Stenberg, . +COPYRIGHT AND PERMISSION NOTICE Copyright (c) 1996 - 2015, Daniel Stenberg, +. All rights reserved. diff --git a/options/license/psfrag b/options/license/psfrag index 4d63df6bbd..a6f0926629 100644 --- a/options/license/psfrag +++ b/options/license/psfrag @@ -1,6 +1,4 @@ -psfrag.dtx - -Copyright (C) 1996 Craig Barratt, Michael C. Grant, and David Carlisle. +psfrag.dtx Copyright (C) 1996 Craig Barratt, Michael C. Grant, and David Carlisle. All rights are reserved. diff --git a/options/license/psutils b/options/license/psutils index e698aecad9..ed031859ba 100644 --- a/options/license/psutils +++ b/options/license/psutils @@ -1,7 +1,5 @@ -PS Utilities Package - -The constituent files of this package listed below are copyright (C) 1991-1995 -Angus J. C. Duggan. +PS Utilities Package The constituent files of this package listed below are +copyright (C) 1991-1995 Angus J. C. Duggan. LICENSE Makefile.msc Makefile.nt Makefile.os2 diff --git a/options/license/xinetd b/options/license/xinetd index 1fc82bfca4..70c0bb8e7a 100644 --- a/options/license/xinetd +++ b/options/license/xinetd @@ -1,6 +1,4 @@ -ORIGINAL LICENSE: This software is - -(c) Copyright 1992 by Panagiotis Tsirigotis +ORIGINAL LICENSE: This software is (c) Copyright 1992 by Panagiotis Tsirigotis The author (Panagiotis Tsirigotis) grants permission to use, copy, and distribute this software and its documentation for any purpose and without fee, provided diff --git a/options/license/xpp b/options/license/xpp index c059c56234..c906815603 100644 --- a/options/license/xpp +++ b/options/license/xpp @@ -1,6 +1,5 @@ -LICENSE FOR THE Extreme! Lab PullParser - -Copyright (c) 2002 The Trustees of Indiana University. All rights reserved. +LICENSE FOR THE Extreme! Lab PullParser Copyright (c) 2002 The Trustees of +Indiana University. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: From b48cad6a2aa4811b65c230ed448c3cc083b9516a Mon Sep 17 00:00:00 2001 From: zeripath Date: Wed, 30 Oct 2019 18:28:14 +0000 Subject: [PATCH 09/19] Adjust the must-change-password help (#8755) --- cmd/admin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/admin.go b/cmd/admin.go index 4346159feb..83ced76c96 100644 --- a/cmd/admin.go +++ b/cmd/admin.go @@ -66,7 +66,7 @@ var ( }, cli.BoolFlag{ Name: "must-change-password", - Usage: "Force the user to change his/her password after initial login", + Usage: "Set this option to false to prevent forcing the user to change their password after initial login, (Default: true)", }, cli.IntFlag{ Name: "random-password-length", From 12864733864f2faa73c7c131f9a421409088f887 Mon Sep 17 00:00:00 2001 From: John Olheiser <42128690+jolheiser@users.noreply.github.com> Date: Wed, 30 Oct 2019 14:22:13 -0500 Subject: [PATCH 10/19] Changelog 1.10.0-rc2 (#8750) (#8754) * 1.10.0-rc2 Signed-off-by: jolheiser Co-Authored-By: jaqra <48099350+jaqra@users.noreply.github.com> --- CHANGELOG.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a88eb1035..6ff277eaf8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,32 @@ This changelog goes through all the changes that have been made in each release without substantial changes to our git log; to see the highlights of what has been added to each release, please refer to the [blog](https://blog.gitea.io). +## [1.10.0-RC2](https://github.com/go-gitea/gitea/releases/tag/v1.10.0-rc2) - 2019-10-30 +* BREAKING + * Fix deadline on update issue or PR via API (#8698) + * Hide some user information via API if user doesn't have enough permission (#8655) (#8657) +* BUGFIXES + * Expose db.SetMaxOpenConns and allow non MySQL dbs to set conn pool params (#8528) (#8618) + * Fix milestone close timestamp (#8728) (#8730) + * Fix 500 when getting user as unauthenticated user (#8653) (#8663) + * Fix 'New Issue Missing Milestone Comment' (#8678) (#8681) + * Use AppSubUrl for more redirections (#8647) (#8651) + * Add SubURL to redirect path (#8632) (#8634) + * Fix template error on account page (#8562) (#8622) + * Allow externalID to be UUID (#8551) (#8624) + * Prevent removal of non-empty emoji panel following selection of duplicate (#8609) (#8623) + * Update heatmap fixtures to restore tests (#8615) (#8616) + * Ensure that diff stats can scroll independently of the diff (#8581) (#8621) + * Webhook: set Content-Type for application/x-www-form-urlencoded (#8600) + * Fix #8582 by handling empty repos (#8587) (#8594) + * Fix bug on pull requests when transfer head repository (#8564) (#8569) + * Add missed close in ServeBlobLFS (#8527) (#8542) + * Ensure that GitRepo is set on Empty repositories (#8539) (#8541) + * Fix migrate mirror 500 bug (#8526) (#8530) + * Fix password complexity regex for special characters (#8524) + * Prevent .code-view from overriding font on icon fonts (#8614) (#8627) + * Allow more than 255 characters for tokens in external_login_user table (#8554) + ## [1.10.0-RC1](https://github.com/go-gitea/gitea/releases/tag/v1.10.0-rc1) - 2019-10-14 * BREAKING * Remove legacy handling of drone token (#8191) From de2f45f95edd06ab8c1e3f61aed3bfc112d83430 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 31 Oct 2019 04:33:10 +0800 Subject: [PATCH 11/19] Move pull list code to a seperate file (#8748) --- models/pull.go | 211 ----------------------------------------- models/pull_list.go | 224 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 224 insertions(+), 211 deletions(-) create mode 100644 models/pull_list.go diff --git a/models/pull.go b/models/pull.go index c6da63ec55..45a1daac46 100644 --- a/models/pull.go +++ b/models/pull.go @@ -16,7 +16,6 @@ import ( "strings" "time" - "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" @@ -26,7 +25,6 @@ import ( "code.gitea.io/gitea/modules/timeutil" "github.com/unknwon/com" - "xorm.io/xorm" ) var pullRequestQueue = sync.NewUniqueQueue(setting.Repository.PullRequestQueueLength) @@ -753,66 +751,6 @@ func newPullRequestAttempt(repo *Repository, pull *Issue, labelIDs []int64, uuid return nil } -// PullRequestsOptions holds the options for PRs -type PullRequestsOptions struct { - Page int - State string - SortType string - Labels []string - MilestoneID int64 -} - -func listPullRequestStatement(baseRepoID int64, opts *PullRequestsOptions) (*xorm.Session, error) { - sess := x.Where("pull_request.base_repo_id=?", baseRepoID) - - sess.Join("INNER", "issue", "pull_request.issue_id = issue.id") - switch opts.State { - case "closed", "open": - sess.And("issue.is_closed=?", opts.State == "closed") - } - - if labelIDs, err := base.StringsToInt64s(opts.Labels); err != nil { - return nil, err - } else if len(labelIDs) > 0 { - sess.Join("INNER", "issue_label", "issue.id = issue_label.issue_id"). - In("issue_label.label_id", labelIDs) - } - - if opts.MilestoneID > 0 { - sess.And("issue.milestone_id=?", opts.MilestoneID) - } - - return sess, nil -} - -// PullRequests returns all pull requests for a base Repo by the given conditions -func PullRequests(baseRepoID int64, opts *PullRequestsOptions) ([]*PullRequest, int64, error) { - if opts.Page <= 0 { - opts.Page = 1 - } - - countSession, err := listPullRequestStatement(baseRepoID, opts) - if err != nil { - log.Error("listPullRequestStatement: %v", err) - return nil, 0, err - } - maxResults, err := countSession.Count(new(PullRequest)) - if err != nil { - log.Error("Count PRs: %v", err) - return nil, maxResults, err - } - - prs := make([]*PullRequest, 0, ItemsPerPage) - findSession, err := listPullRequestStatement(baseRepoID, opts) - sortIssuesSession(findSession, opts.SortType) - if err != nil { - log.Error("listPullRequestStatement: %v", err) - return nil, maxResults, err - } - findSession.Limit(ItemsPerPage, (opts.Page-1)*ItemsPerPage) - return prs, maxResults, findSession.Find(&prs) -} - // GetUnmergedPullRequest returns a pull request that is open and has not been merged // by given head/base and repo/branch. func GetUnmergedPullRequest(headRepoID, baseRepoID int64, headBranch, baseBranch string) (*PullRequest, error) { @@ -831,17 +769,6 @@ func GetUnmergedPullRequest(headRepoID, baseRepoID int64, headBranch, baseBranch return pr, nil } -// GetUnmergedPullRequestsByHeadInfo returns all pull requests that are open and has not been merged -// by given head information (repo and branch). -func GetUnmergedPullRequestsByHeadInfo(repoID int64, branch string) ([]*PullRequest, error) { - prs := make([]*PullRequest, 0, 2) - return prs, x. - Where("head_repo_id = ? AND head_branch = ? AND has_merged = ? AND issue.is_closed = ?", - repoID, branch, false, false). - Join("INNER", "issue", "issue.id = pull_request.issue_id"). - Find(&prs) -} - // GetLatestPullRequestByHeadInfo returns the latest pull request (regardless of its status) // by given head information (repo and branch). func GetLatestPullRequestByHeadInfo(repoID int64, branch string) (*PullRequest, error) { @@ -856,17 +783,6 @@ func GetLatestPullRequestByHeadInfo(repoID int64, branch string) (*PullRequest, return pr, err } -// GetUnmergedPullRequestsByBaseInfo returns all pull requests that are open and has not been merged -// by given base information (repo and branch). -func GetUnmergedPullRequestsByBaseInfo(repoID int64, branch string) ([]*PullRequest, error) { - prs := make([]*PullRequest, 0, 2) - return prs, x. - Where("base_repo_id=? AND base_branch=? AND has_merged=? AND issue.is_closed=?", - repoID, branch, false, false). - Join("INNER", "issue", "issue.id=pull_request.issue_id"). - Find(&prs) -} - // GetPullRequestByIndex returns a pull request by the given index func GetPullRequestByIndex(repoID int64, index int64) (*PullRequest, error) { pr := &PullRequest{ @@ -1035,72 +951,6 @@ func (pr *PullRequest) AddToTaskQueue() { }) } -// PullRequestList defines a list of pull requests -type PullRequestList []*PullRequest - -func (prs PullRequestList) loadAttributes(e Engine) error { - if len(prs) == 0 { - return nil - } - - // Load issues. - issueIDs := prs.getIssueIDs() - issues := make([]*Issue, 0, len(issueIDs)) - if err := e. - Where("id > 0"). - In("id", issueIDs). - Find(&issues); err != nil { - return fmt.Errorf("find issues: %v", err) - } - - set := make(map[int64]*Issue) - for i := range issues { - set[issues[i].ID] = issues[i] - } - for i := range prs { - prs[i].Issue = set[prs[i].IssueID] - } - return nil -} - -func (prs PullRequestList) getIssueIDs() []int64 { - issueIDs := make([]int64, 0, len(prs)) - for i := range prs { - issueIDs = append(issueIDs, prs[i].IssueID) - } - return issueIDs -} - -// LoadAttributes load all the prs attributes -func (prs PullRequestList) LoadAttributes() error { - return prs.loadAttributes(x) -} - -func (prs PullRequestList) invalidateCodeComments(e Engine, doer *User, repo *git.Repository, branch string) error { - if len(prs) == 0 { - return nil - } - issueIDs := prs.getIssueIDs() - var codeComments []*Comment - if err := e. - Where("type = ? and invalidated = ?", CommentTypeCode, false). - In("issue_id", issueIDs). - Find(&codeComments); err != nil { - return fmt.Errorf("find code comments: %v", err) - } - for _, comment := range codeComments { - if err := comment.CheckInvalidation(repo, doer, branch); err != nil { - return err - } - } - return nil -} - -// InvalidateCodeComments will lookup the prs for code comments which got invalidated by change -func (prs PullRequestList) InvalidateCodeComments(doer *User, repo *git.Repository, branch string) error { - return prs.invalidateCodeComments(x, doer, repo, branch) -} - // checkAndUpdateStatus checks if pull request is possible to leaving checking status, // and set to be either conflict or mergeable. func (pr *PullRequest) checkAndUpdateStatus() { @@ -1152,64 +1002,3 @@ func (pr *PullRequest) GetWorkInProgressPrefix() string { } return "" } - -// TestPullRequests checks and tests untested patches of pull requests. -// TODO: test more pull requests at same time. -func TestPullRequests() { - prs := make([]*PullRequest, 0, 10) - - err := x.Where("status = ?", PullRequestStatusChecking).Find(&prs) - if err != nil { - log.Error("Find Checking PRs: %v", err) - return - } - - var checkedPRs = make(map[int64]struct{}) - - // Update pull request status. - for _, pr := range prs { - checkedPRs[pr.ID] = struct{}{} - if err := pr.GetBaseRepo(); err != nil { - log.Error("GetBaseRepo: %v", err) - continue - } - if pr.manuallyMerged() { - continue - } - if err := pr.testPatch(x); err != nil { - log.Error("testPatch: %v", err) - continue - } - - pr.checkAndUpdateStatus() - } - - // Start listening on new test requests. - for prID := range pullRequestQueue.Queue() { - log.Trace("TestPullRequests[%v]: processing test task", prID) - pullRequestQueue.Remove(prID) - - id := com.StrTo(prID).MustInt64() - if _, ok := checkedPRs[id]; ok { - continue - } - - pr, err := GetPullRequestByID(id) - if err != nil { - log.Error("GetPullRequestByID[%s]: %v", prID, err) - continue - } else if pr.manuallyMerged() { - continue - } else if err = pr.testPatch(x); err != nil { - log.Error("testPatch[%d]: %v", pr.ID, err) - continue - } - - pr.checkAndUpdateStatus() - } -} - -// InitTestPullRequests runs the task to test all the checking status pull requests -func InitTestPullRequests() { - go TestPullRequests() -} diff --git a/models/pull_list.go b/models/pull_list.go new file mode 100644 index 0000000000..4ec6fdde3b --- /dev/null +++ b/models/pull_list.go @@ -0,0 +1,224 @@ +// Copyright 2019 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package models + +import ( + "fmt" + + "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/log" + "github.com/unknwon/com" + "xorm.io/xorm" +) + +// PullRequestsOptions holds the options for PRs +type PullRequestsOptions struct { + Page int + State string + SortType string + Labels []string + MilestoneID int64 +} + +func listPullRequestStatement(baseRepoID int64, opts *PullRequestsOptions) (*xorm.Session, error) { + sess := x.Where("pull_request.base_repo_id=?", baseRepoID) + + sess.Join("INNER", "issue", "pull_request.issue_id = issue.id") + switch opts.State { + case "closed", "open": + sess.And("issue.is_closed=?", opts.State == "closed") + } + + if labelIDs, err := base.StringsToInt64s(opts.Labels); err != nil { + return nil, err + } else if len(labelIDs) > 0 { + sess.Join("INNER", "issue_label", "issue.id = issue_label.issue_id"). + In("issue_label.label_id", labelIDs) + } + + if opts.MilestoneID > 0 { + sess.And("issue.milestone_id=?", opts.MilestoneID) + } + + return sess, nil +} + +// GetUnmergedPullRequestsByHeadInfo returns all pull requests that are open and has not been merged +// by given head information (repo and branch). +func GetUnmergedPullRequestsByHeadInfo(repoID int64, branch string) ([]*PullRequest, error) { + prs := make([]*PullRequest, 0, 2) + return prs, x. + Where("head_repo_id = ? AND head_branch = ? AND has_merged = ? AND issue.is_closed = ?", + repoID, branch, false, false). + Join("INNER", "issue", "issue.id = pull_request.issue_id"). + Find(&prs) +} + +// GetUnmergedPullRequestsByBaseInfo returns all pull requests that are open and has not been merged +// by given base information (repo and branch). +func GetUnmergedPullRequestsByBaseInfo(repoID int64, branch string) ([]*PullRequest, error) { + prs := make([]*PullRequest, 0, 2) + return prs, x. + Where("base_repo_id=? AND base_branch=? AND has_merged=? AND issue.is_closed=?", + repoID, branch, false, false). + Join("INNER", "issue", "issue.id=pull_request.issue_id"). + Find(&prs) +} + +// PullRequests returns all pull requests for a base Repo by the given conditions +func PullRequests(baseRepoID int64, opts *PullRequestsOptions) ([]*PullRequest, int64, error) { + if opts.Page <= 0 { + opts.Page = 1 + } + + countSession, err := listPullRequestStatement(baseRepoID, opts) + if err != nil { + log.Error("listPullRequestStatement: %v", err) + return nil, 0, err + } + maxResults, err := countSession.Count(new(PullRequest)) + if err != nil { + log.Error("Count PRs: %v", err) + return nil, maxResults, err + } + + prs := make([]*PullRequest, 0, ItemsPerPage) + findSession, err := listPullRequestStatement(baseRepoID, opts) + sortIssuesSession(findSession, opts.SortType) + if err != nil { + log.Error("listPullRequestStatement: %v", err) + return nil, maxResults, err + } + findSession.Limit(ItemsPerPage, (opts.Page-1)*ItemsPerPage) + return prs, maxResults, findSession.Find(&prs) +} + +// PullRequestList defines a list of pull requests +type PullRequestList []*PullRequest + +func (prs PullRequestList) loadAttributes(e Engine) error { + if len(prs) == 0 { + return nil + } + + // Load issues. + issueIDs := prs.getIssueIDs() + issues := make([]*Issue, 0, len(issueIDs)) + if err := e. + Where("id > 0"). + In("id", issueIDs). + Find(&issues); err != nil { + return fmt.Errorf("find issues: %v", err) + } + + set := make(map[int64]*Issue) + for i := range issues { + set[issues[i].ID] = issues[i] + } + for i := range prs { + prs[i].Issue = set[prs[i].IssueID] + } + return nil +} + +func (prs PullRequestList) getIssueIDs() []int64 { + issueIDs := make([]int64, 0, len(prs)) + for i := range prs { + issueIDs = append(issueIDs, prs[i].IssueID) + } + return issueIDs +} + +// LoadAttributes load all the prs attributes +func (prs PullRequestList) LoadAttributes() error { + return prs.loadAttributes(x) +} + +func (prs PullRequestList) invalidateCodeComments(e Engine, doer *User, repo *git.Repository, branch string) error { + if len(prs) == 0 { + return nil + } + issueIDs := prs.getIssueIDs() + var codeComments []*Comment + if err := e. + Where("type = ? and invalidated = ?", CommentTypeCode, false). + In("issue_id", issueIDs). + Find(&codeComments); err != nil { + return fmt.Errorf("find code comments: %v", err) + } + for _, comment := range codeComments { + if err := comment.CheckInvalidation(repo, doer, branch); err != nil { + return err + } + } + return nil +} + +// InvalidateCodeComments will lookup the prs for code comments which got invalidated by change +func (prs PullRequestList) InvalidateCodeComments(doer *User, repo *git.Repository, branch string) error { + return prs.invalidateCodeComments(x, doer, repo, branch) +} + +// TestPullRequests checks and tests untested patches of pull requests. +// TODO: test more pull requests at same time. +func TestPullRequests() { + prs := make([]*PullRequest, 0, 10) + + err := x.Where("status = ?", PullRequestStatusChecking).Find(&prs) + if err != nil { + log.Error("Find Checking PRs: %v", err) + return + } + + var checkedPRs = make(map[int64]struct{}) + + // Update pull request status. + for _, pr := range prs { + checkedPRs[pr.ID] = struct{}{} + if err := pr.GetBaseRepo(); err != nil { + log.Error("GetBaseRepo: %v", err) + continue + } + if pr.manuallyMerged() { + continue + } + if err := pr.testPatch(x); err != nil { + log.Error("testPatch: %v", err) + continue + } + + pr.checkAndUpdateStatus() + } + + // Start listening on new test requests. + for prID := range pullRequestQueue.Queue() { + log.Trace("TestPullRequests[%v]: processing test task", prID) + pullRequestQueue.Remove(prID) + + id := com.StrTo(prID).MustInt64() + if _, ok := checkedPRs[id]; ok { + continue + } + + pr, err := GetPullRequestByID(id) + if err != nil { + log.Error("GetPullRequestByID[%s]: %v", prID, err) + continue + } else if pr.manuallyMerged() { + continue + } else if err = pr.testPatch(x); err != nil { + log.Error("testPatch[%d]: %v", pr.ID, err) + continue + } + + pr.checkAndUpdateStatus() + } +} + +// InitTestPullRequests runs the task to test all the checking status pull requests +func InitTestPullRequests() { + go TestPullRequests() +} From 74323965140e25b8a998d499fe4c97255918747f Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Wed, 30 Oct 2019 20:34:47 +0000 Subject: [PATCH 12/19] [skip ci] Updated translations via Crowdin --- options/locale/locale_de-DE.ini | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini index f18b74e3b1..3b4ae38f5a 100644 --- a/options/locale/locale_de-DE.ini +++ b/options/locale/locale_de-DE.ini @@ -11,7 +11,7 @@ register=Registrieren website=Webseite version=Version page=Seite -template=Vorlage +template=Template language=Sprache notifications=Benachrichtigungen create_new=Erstellen… @@ -702,6 +702,7 @@ editor.preview_changes=Vorschau der Änderungen editor.cannot_edit_lfs_files=LFS-Dateien können im Webinterface nicht bearbeitet werden. editor.cannot_edit_non_text_files=Binärdateien können nicht im Webinterface bearbeitet werden. editor.edit_this_file=Datei bearbeiten +editor.this_file_locked=Datei ist gesperrt editor.must_be_on_a_branch=Du musst dich in einem Branch befinden, um Änderungen an dieser Datei vorzuschlagen oder vorzunehmen. editor.fork_before_edit=Du musst dieses Repository forken, um Änderungen an dieser Datei vorzuschlagen oder vorzunehmen. editor.delete_this_file=Datei löschen @@ -976,6 +977,7 @@ issues.review.review=Review issues.review.reviewers=Reviewer issues.review.show_outdated=Veraltete anzeigen issues.review.hide_outdated=Veraltete ausblenden +issues.assignee.error=Aufgrund eines unerwarteten Fehlers konnten nicht alle Beauftragten hinzugefügt werden. pulls.desc=Pull-Requests und Code-Reviews aktivieren. pulls.new=Neuer Pull-Request @@ -1334,6 +1336,7 @@ settings.protect_this_branch=Branch-Schutz aktivieren settings.protect_this_branch_desc=Löschen verhindern und „force pushing” von Git auf dieser Branch deaktivieren. settings.protect_whitelist_committers=Push-Whitelist aktivieren settings.protect_whitelist_committers_desc=Erlaube, dass Benutzer oder Teams, die auf der Whitelist stehen, auf diese Branch "pushen" dürfen (aber nicht "force pushen"). +settings.protect_whitelist_deploy_keys=Deploy-Schlüssel mit Schreibzugriff zum Push whitelisten settings.protect_whitelist_users=Nutzer, die pushen dürfen: settings.protect_whitelist_search_users=Benutzer suchen… settings.protect_whitelist_teams=Teams, die pushen dürfen: @@ -1375,6 +1378,20 @@ settings.unarchive.text=Durch das Aufheben der Archivierung kann das Repo wieder settings.unarchive.success=Die Archivierung des Repos wurde erfolgreich wieder rückgängig gemacht. settings.unarchive.error=Beim Versuch, die Archivierung des Repos aufzuheben, ist ein Fehler aufgetreten. Weitere Details finden sich im Log. settings.update_avatar_success=Der Repository-Avatar wurde aktualisiert. +settings.lfs=LFS +settings.lfs_filelist=LFS-Dateien, die in diesem Repository gespeichert sind +settings.lfs_no_lfs_files=In diesem Repository sind keine LFS-Dateien gespeichert +settings.lfs_findcommits=Commits finden +settings.lfs_lfs_file_no_commits=Keine Commits für diese LFS-Datei gefunden +settings.lfs_delete=LFS-Datei mit OID %s löschen +settings.lfs_delete_warning=Das Löschen einer LFS-Datei kann dazu führen, dass 'Objekt existiert nicht'-Fehler beim Checkout auftreten. Bist du sicher? +settings.lfs_findpointerfiles=Pointer-Dateien finden +settings.lfs_pointers.found=%d Blob-Zeiger gefunden - %d assoziiert, %d nicht assoziiert (%d fehlend im Speicher) +settings.lfs_pointers.sha=Blob SHA +settings.lfs_pointers.oid=OID +settings.lfs_pointers.inRepo=Im Repo +settings.lfs_pointers.exists=Existiert im Speicher +settings.lfs_pointers.accessible=Nutzer hat Zugriff diff.browse_source=Quellcode durchsuchen diff.parent=Ursprung From 690a8ec502ff2e162b6db9cfe1f0555cf6b37323 Mon Sep 17 00:00:00 2001 From: John Olheiser <42128690+jolheiser@users.noreply.github.com> Date: Wed, 30 Oct 2019 16:22:20 -0500 Subject: [PATCH 13/19] Changelog 1.9.5 (#8753) (#8756) (#8758) Signed-off-by: jolheiser --- CHANGELOG.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ff277eaf8..a92a61b497 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -289,6 +289,30 @@ been added to each release, please refer to the [blog](https://blog.gitea.io). * wiki - editor - add buttons 'inline code', 'empty checkbox', 'checked checkbox' (#7243) * Fix Statuses API only shows first 10 statuses: Add paging and extend API GetCommitStatuses (#7141) +## [1.9.5](https://github.com/go-gitea/gitea/releases/tag/v1.9.5) - 2019-10-30 +* BREAKING + * Hide some user information via API if user doesn't have enough permission (#8655) (#8658) +* BUGFIXES + * Fix milestone close timestamp (#8728) (#8731) + * Fix deadline on update issue or PR via API (#8699) + * Fix 'New Issue Missing Milestone Comment' (#8678) (#8682) + * Fix 500 when getting user as unauthenticated user (#8653) (#8662) + * Use AppSubUrl for more redirections (#8647) (#8652) + * Add SubURL to redirect path (#8632) (#8634) (#8640) + * Fix #8582 by handling empty repos (#8587) (#8593) + * Fix bug on pull requests when transfer head repository (#8571) + * Add missed close in ServeBlobLFS (#8527) (#8543) + * Return false if provided branch name is empty for IsBranchExist (#8485) (#8492) + * Create .ssh dir as necessary (#8369) (#8486) (#8489) + * Restore functionality for early gits (#7775) (#8476) + * Add check for empty set when dropping indexes during migration (#8475) + * Ensure Request Body Readers are closed in LFS server (#8454) (#8459) + * Ensure that LFS files are relative to the LFS content path (#8455) (#8458) +* SECURITY + * Ignore mentions for users with no access (#8395) (#8484) +* TESTING + * Update heatmap fixtures to restore tests (#8615) (#8617) + ## [1.9.4](https://github.com/go-gitea/gitea/releases/tag/v1.9.4) - 2019-10-08 * BUGFIXES * Highlight issue references (#8101) (#8404) From 086a46994a9f59ba06bfacdf2041817ef2f6671c Mon Sep 17 00:00:00 2001 From: Lauris BH Date: Thu, 31 Oct 2019 03:06:25 +0200 Subject: [PATCH 14/19] Rewrite markdown rendering to blackfriday v2 and rewrite orgmode rendering to go-org (#8560) * Rewrite markdown rendering to blackfriday v2.0 * Fix style * Fix go mod with golang 1.13 * Fix blackfriday v2 import * Inital orgmode renderer migration to go-org * Vendor go-org dependency * Ignore errors :/ * Update go-org to latest version * Update test * Fix go-org test * Remove unneeded code * Fix comments * Fix markdown test * Fix blackfriday regression rendering HTML block --- go.mod | 9 +- go.sum | 16 +- modules/markup/html_test.go | 4 +- modules/markup/markdown/markdown.go | 217 ++-- modules/markup/markdown/markdown_test.go | 8 +- modules/markup/mdstripper/mdstripper.go | 258 ++--- modules/markup/orgmode/orgmode.go | 100 +- modules/markup/orgmode/orgmode_test.go | 10 +- .../chaseadamsio/goorgeous/.gitignore | 1 - .../chaseadamsio/goorgeous/.travis.yml | 12 - .../chaseadamsio/goorgeous/README.org | 66 -- .../chaseadamsio/goorgeous/goorgeous.go | 803 --------------- .../chaseadamsio/goorgeous/gopher.gif | Bin 15232 -> 0 bytes .../chaseadamsio/goorgeous/gopher_small.gif | Bin 3270 -> 0 bytes .../chaseadamsio/goorgeous/header.go | 70 -- .../go-org}/LICENSE | 2 +- .../niklasfasching/go-org/org/block.go | 84 ++ .../niklasfasching/go-org/org/document.go | 260 +++++ .../niklasfasching/go-org/org/drawer.go | 97 ++ .../niklasfasching/go-org/org/footnote.go | 35 + .../niklasfasching/go-org/org/fuzz.go | 27 + .../niklasfasching/go-org/org/headline.go | 101 ++ .../niklasfasching/go-org/org/html_entity.go | 437 ++++++++ .../niklasfasching/go-org/org/html_writer.go | 504 ++++++++++ .../niklasfasching/go-org/org/inline.go | 357 +++++++ .../niklasfasching/go-org/org/keyword.go | 184 ++++ .../niklasfasching/go-org/org/list.go | 114 +++ .../niklasfasching/go-org/org/org_writer.go | 334 ++++++ .../niklasfasching/go-org/org/paragraph.go | 46 + .../niklasfasching/go-org/org/table.go | 130 +++ .../niklasfasching/go-org/org/util.go | 19 + .../niklasfasching/go-org/org/writer.go | 103 ++ vendor/github.com/russross/blackfriday/doc.go | 32 - .../github.com/russross/blackfriday/html.go | 938 ----------------- .../github.com/russross/blackfriday/latex.go | 334 ------ .../russross/blackfriday/{ => v2}/.gitignore | 0 .../russross/blackfriday/{ => v2}/.travis.yml | 21 +- .../russross/blackfriday/{ => v2}/LICENSE.txt | 0 .../russross/blackfriday/{ => v2}/README.md | 122 +-- .../russross/blackfriday/{ => v2}/block.go | 853 +++++++++------- .../github.com/russross/blackfriday/v2/doc.go | 18 + .../github.com/russross/blackfriday/v2/esc.go | 34 + .../github.com/russross/blackfriday/v2/go.mod | 1 + .../russross/blackfriday/v2/html.go | 949 ++++++++++++++++++ .../russross/blackfriday/{ => v2}/inline.go | 570 ++++++----- .../russross/blackfriday/{ => v2}/markdown.go | 685 ++++++------- .../russross/blackfriday/v2/node.go | 354 +++++++ .../blackfriday/{ => v2}/smartypants.go | 139 +-- .../sanitized_anchor_name/.travis.yml | 6 +- .../shurcooL/sanitized_anchor_name/LICENSE | 10 +- .../shurcooL/sanitized_anchor_name/README.md | 6 +- .../shurcooL/sanitized_anchor_name/go.mod | 1 + .../shurcooL/sanitized_anchor_name/main.go | 2 +- vendor/golang.org/x/net/html/token.go | 6 + vendor/modules.txt | 12 +- 55 files changed, 5769 insertions(+), 3732 deletions(-) delete mode 100644 vendor/github.com/chaseadamsio/goorgeous/.gitignore delete mode 100644 vendor/github.com/chaseadamsio/goorgeous/.travis.yml delete mode 100644 vendor/github.com/chaseadamsio/goorgeous/README.org delete mode 100644 vendor/github.com/chaseadamsio/goorgeous/goorgeous.go delete mode 100644 vendor/github.com/chaseadamsio/goorgeous/gopher.gif delete mode 100644 vendor/github.com/chaseadamsio/goorgeous/gopher_small.gif delete mode 100644 vendor/github.com/chaseadamsio/goorgeous/header.go rename vendor/github.com/{chaseadamsio/goorgeous => niklasfasching/go-org}/LICENSE (94%) create mode 100644 vendor/github.com/niklasfasching/go-org/org/block.go create mode 100644 vendor/github.com/niklasfasching/go-org/org/document.go create mode 100644 vendor/github.com/niklasfasching/go-org/org/drawer.go create mode 100644 vendor/github.com/niklasfasching/go-org/org/footnote.go create mode 100644 vendor/github.com/niklasfasching/go-org/org/fuzz.go create mode 100644 vendor/github.com/niklasfasching/go-org/org/headline.go create mode 100644 vendor/github.com/niklasfasching/go-org/org/html_entity.go create mode 100644 vendor/github.com/niklasfasching/go-org/org/html_writer.go create mode 100644 vendor/github.com/niklasfasching/go-org/org/inline.go create mode 100644 vendor/github.com/niklasfasching/go-org/org/keyword.go create mode 100644 vendor/github.com/niklasfasching/go-org/org/list.go create mode 100644 vendor/github.com/niklasfasching/go-org/org/org_writer.go create mode 100644 vendor/github.com/niklasfasching/go-org/org/paragraph.go create mode 100644 vendor/github.com/niklasfasching/go-org/org/table.go create mode 100644 vendor/github.com/niklasfasching/go-org/org/util.go create mode 100644 vendor/github.com/niklasfasching/go-org/org/writer.go delete mode 100644 vendor/github.com/russross/blackfriday/doc.go delete mode 100644 vendor/github.com/russross/blackfriday/html.go delete mode 100644 vendor/github.com/russross/blackfriday/latex.go rename vendor/github.com/russross/blackfriday/{ => v2}/.gitignore (100%) rename vendor/github.com/russross/blackfriday/{ => v2}/.travis.yml (50%) rename vendor/github.com/russross/blackfriday/{ => v2}/LICENSE.txt (100%) rename vendor/github.com/russross/blackfriday/{ => v2}/README.md (69%) rename vendor/github.com/russross/blackfriday/{ => v2}/block.go (54%) create mode 100644 vendor/github.com/russross/blackfriday/v2/doc.go create mode 100644 vendor/github.com/russross/blackfriday/v2/esc.go create mode 100644 vendor/github.com/russross/blackfriday/v2/go.mod create mode 100644 vendor/github.com/russross/blackfriday/v2/html.go rename vendor/github.com/russross/blackfriday/{ => v2}/inline.go (63%) rename vendor/github.com/russross/blackfriday/{ => v2}/markdown.go (50%) create mode 100644 vendor/github.com/russross/blackfriday/v2/node.go rename vendor/github.com/russross/blackfriday/{ => v2}/smartypants.go (66%) create mode 100644 vendor/github.com/shurcooL/sanitized_anchor_name/go.mod diff --git a/go.mod b/go.mod index e1bbd9ac89..02f0c46f22 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,6 @@ require ( github.com/blevesearch/go-porterstemmer v0.0.0-20141230013033-23a2c8e5cf1f // indirect github.com/blevesearch/segment v0.0.0-20160105220820-db70c57796cc // indirect github.com/boombuler/barcode v0.0.0-20161226211916-fe0f26ff6d26 // indirect - github.com/chaseadamsio/goorgeous v0.0.0-20170901132237-098da33fde5f github.com/couchbase/vellum v0.0.0-20190111184608-e91b68ff3efe // indirect github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d // indirect github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 // indirect @@ -73,6 +72,7 @@ require ( github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae // indirect github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5 + github.com/niklasfasching/go-org v0.1.7 github.com/oliamb/cutter v0.2.2 github.com/philhofer/fwd v1.0.0 // indirect github.com/pkg/errors v0.8.1 @@ -80,12 +80,13 @@ require ( github.com/prometheus/client_golang v1.1.0 github.com/prometheus/procfs v0.0.4 // indirect github.com/remyoudompheng/bigfft v0.0.0-20190321074620-2f0d2b0e0001 // indirect - github.com/russross/blackfriday v0.0.0-20180428102519-11635eb403ff + github.com/russross/blackfriday v2.0.0+incompatible // indirect + github.com/russross/blackfriday/v2 v2.0.1 github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca // indirect github.com/satori/go.uuid v1.2.0 github.com/sergi/go-diff v1.0.0 github.com/shurcooL/httpfs v0.0.0-20190527155220-6a4d4a70508b // indirect - github.com/shurcooL/sanitized_anchor_name v0.0.0-20160918041101-1dba4b3954bc // indirect + github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd github.com/steveyen/gtreap v0.0.0-20150807155958-0abe01ef9be2 // indirect github.com/stretchr/testify v1.4.0 @@ -100,7 +101,7 @@ require ( github.com/willf/bitset v0.0.0-20180426185212-8ce1146b8621 // indirect github.com/yohcop/openid-go v0.0.0-20160914080427-2c050d2dae53 golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad - golang.org/x/net v0.0.0-20190909003024-a7b16738d86b + golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 golang.org/x/sys v0.0.0-20190910064555-bbd175535a8b golang.org/x/text v0.3.2 diff --git a/go.sum b/go.sum index 2eeaa79810..7445469d7e 100644 --- a/go.sum +++ b/go.sum @@ -86,8 +86,6 @@ github.com/boombuler/barcode v0.0.0-20161226211916-fe0f26ff6d26/go.mod h1:paBWMc github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668 h1:U/lr3Dgy4WK+hNk4tyD+nuGjpVLPEHuJSFXMw11/HPA= github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/chaseadamsio/goorgeous v0.0.0-20170901132237-098da33fde5f h1:REH9VH5ubNR0skLaOxK7TRJeRbE2dDfvaouQo8FsRcA= -github.com/chaseadamsio/goorgeous v0.0.0-20170901132237-098da33fde5f/go.mod h1:6QaC0vFoKWYDth94dHFNgRT2YkT5FHdQp/Yx15aAAi0= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/corbym/gocrest v1.0.3 h1:gwEdq6RkTmq+09CTuM29DfKOCtZ7G7bcyxs3IZ6EVdU= github.com/corbym/gocrest v1.0.3/go.mod h1:maVFL5lbdS2PgfOQgGRWDYTeunSWQeiEgoNdTABShCs= @@ -425,6 +423,10 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5 h1:BvoENQQU+fZ9uukda/RzCAL/191HHwJA5b13R6diVlY= github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= +github.com/niklasfasching/go-org v0.1.6 h1:F521WcqRNl8OJumlgAnekZgERaTA2HpfOYYfVEKOeI8= +github.com/niklasfasching/go-org v0.1.6/go.mod h1:AsLD6X7djzRIz4/RFZu8vwRL0VGjUvGZCCH1Nz0VdrU= +github.com/niklasfasching/go-org v0.1.7 h1:t3V+3XnS/7BhKv/7SlMUa8FvAiq577/a1T3D7mLIRXE= +github.com/niklasfasching/go-org v0.1.7/go.mod h1:AsLD6X7djzRIz4/RFZu8vwRL0VGjUvGZCCH1Nz0VdrU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/oliamb/cutter v0.2.2 h1:Lfwkya0HHNU1YLnGv2hTkzHfasrSMkgv4Dn+5rmlk3k= github.com/oliamb/cutter v0.2.2/go.mod h1:4BenG2/4GuRBDbVm/OPahDVqbrOemzpPiG5mi1iryBU= @@ -487,8 +489,10 @@ github.com/remyoudompheng/bigfft v0.0.0-20190321074620-2f0d2b0e0001/go.mod h1:qq github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/russross/blackfriday v0.0.0-20180428102519-11635eb403ff h1:g9ZlAHmkc/h5So+OjNCkZWh+FjuKEOOOoyRkqlGA8+c= -github.com/russross/blackfriday v0.0.0-20180428102519-11635eb403ff/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday v2.0.0+incompatible h1:cBXrhZNUf9C+La9/YpS+UHpUT8YD6Td9ZMSU9APFcsk= +github.com/russross/blackfriday v2.0.0+incompatible/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca h1:NugYot0LIVPxTvN8n+Kvkn6TrbMyxQiuvKdEwFdR9vI= github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= @@ -499,6 +503,8 @@ github.com/shurcooL/httpfs v0.0.0-20190527155220-6a4d4a70508b h1:4kg1wyftSKxLtnP github.com/shurcooL/httpfs v0.0.0-20190527155220-6a4d4a70508b/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/sanitized_anchor_name v0.0.0-20160918041101-1dba4b3954bc h1:3wIrJvFb3Pf6B/2mDBnN1G5IfUVev4X5apadQlWOczE= github.com/shurcooL/sanitized_anchor_name v0.0.0-20160918041101-1dba4b3954bc/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd h1:ug7PpSOB5RBPK1Kg6qskGBoP3Vnj/aNYFTznWvlkGo0= github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw= @@ -650,6 +656,8 @@ golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190909003024-a7b16738d86b h1:XfVGCX+0T4WOStkaOsJRllbsiImhB2jgVBGc9L0lPGc= golang.org/x/net v0.0.0-20190909003024-a7b16738d86b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271 h1:N66aaryRB3Ax92gH0v3hp1QYZ3zWWCCUR/j8Ifh45Ss= +golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180620175406-ef147856a6dd/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421 h1:Wo7BWFiOk0QRFMLYMqJGFMd9CgUAcGx7V+qEg/h5IBI= diff --git a/modules/markup/html_test.go b/modules/markup/html_test.go index 91ef320b40..07747e97e1 100644 --- a/modules/markup/html_test.go +++ b/modules/markup/html_test.go @@ -323,6 +323,6 @@ func TestRender_ShortLinks(t *testing.T) { `

`) test( "

[[foobar]]

", - `

[[foobar]]

`, - `

[[foobar]]

`) + `

[[foobar]]

`, + `

[[foobar]]

`) } diff --git a/modules/markup/markdown/markdown.go b/modules/markup/markdown/markdown.go index d9fc768891..ff78d7ea3a 100644 --- a/modules/markup/markdown/markdown.go +++ b/modules/markup/markdown/markdown.go @@ -7,13 +7,14 @@ package markdown import ( "bytes" + "io" "strings" "code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" - "github.com/russross/blackfriday" + "github.com/russross/blackfriday/v2" ) // Renderer is a extended version of underlying render object. @@ -25,134 +26,138 @@ type Renderer struct { var byteMailto = []byte("mailto:") -// Link defines how formal links should be processed to produce corresponding HTML elements. -func (r *Renderer) Link(out *bytes.Buffer, link []byte, title []byte, content []byte) { - // special case: this is not a link, a hash link or a mailto:, so it's a - // relative URL - if len(link) > 0 && !markup.IsLink(link) && - link[0] != '#' && !bytes.HasPrefix(link, byteMailto) { - lnk := string(link) +var htmlEscaper = [256][]byte{ + '&': []byte("&"), + '<': []byte("<"), + '>': []byte(">"), + '"': []byte("""), +} + +func escapeHTML(w io.Writer, s []byte) { + var start, end int + for end < len(s) { + escSeq := htmlEscaper[s[end]] + if escSeq != nil { + _, _ = w.Write(s[start:end]) + _, _ = w.Write(escSeq) + start = end + 1 + } + end++ + } + if start < len(s) && end <= len(s) { + _, _ = w.Write(s[start:end]) + } +} + +// RenderNode is a default renderer of a single node of a syntax tree. For +// block nodes it will be called twice: first time with entering=true, second +// time with entering=false, so that it could know when it's working on an open +// tag and when on close. It writes the result to w. +// +// The return value is a way to tell the calling walker to adjust its walk +// pattern: e.g. it can terminate the traversal by returning Terminate. Or it +// can ask the walker to skip a subtree of this node by returning SkipChildren. +// The typical behavior is to return GoToNext, which asks for the usual +// traversal to the next node. +func (r *Renderer) RenderNode(w io.Writer, node *blackfriday.Node, entering bool) blackfriday.WalkStatus { + switch node.Type { + case blackfriday.Image: + prefix := r.URLPrefix if r.IsWiki { - lnk = util.URLJoin("wiki", lnk) + prefix = util.URLJoin(prefix, "wiki", "raw") } - mLink := util.URLJoin(r.URLPrefix, lnk) - link = []byte(mLink) - } - - if len(content) > 10 && string(content[0:9]) == " 0 { - out.WriteByte('\n') - } - - if flags&blackfriday.LIST_TYPE_DEFINITION != 0 { - out.WriteString("
") - } else if flags&blackfriday.LIST_TYPE_ORDERED != 0 { - out.WriteString("
    ") - } else { - out.WriteString("
      ") - } - if !text() { - out.Truncate(marker) - return - } - if flags&blackfriday.LIST_TYPE_DEFINITION != 0 { - out.WriteString("
\n") - } else if flags&blackfriday.LIST_TYPE_ORDERED != 0 { - out.WriteString("\n") - } else { - out.WriteString("\n") - } -} - -// ListItem defines how list items should be processed to produce corresponding HTML elements. -func (r *Renderer) ListItem(out *bytes.Buffer, text []byte, flags int) { - // Detect procedures to draw checkboxes. - prefix := "" - if bytes.HasPrefix(text, []byte("

")) { - prefix = "

" - } - switch { - case bytes.HasPrefix(text, []byte(prefix+"[ ] ")): - text = append([]byte(``), text[3+len(prefix):]...) - if prefix != "" { - text = bytes.Replace(text, []byte(prefix), []byte{}, 1) + prefix = strings.Replace(prefix, "/src/", "/media/", 1) + link := node.LinkData.Destination + if len(link) > 0 && !markup.IsLink(link) { + lnk := string(link) + lnk = util.URLJoin(prefix, lnk) + lnk = strings.Replace(lnk, " ", "+", -1) + link = []byte(lnk) } - case bytes.HasPrefix(text, []byte(prefix+"[x] ")): - text = append([]byte(``), text[3+len(prefix):]...) - if prefix != "" { - text = bytes.Replace(text, []byte(prefix), []byte{}, 1) + node.LinkData.Destination = link + // Render link around image only if parent is not link already + if node.Parent != nil && node.Parent.Type != blackfriday.Link { + if entering { + _, _ = w.Write([]byte(``)) + return r.Renderer.RenderNode(w, node, entering) + } + s := r.Renderer.RenderNode(w, node, entering) + _, _ = w.Write([]byte(``)) + return s + } + return r.Renderer.RenderNode(w, node, entering) + case blackfriday.Link: + // special case: this is not a link, a hash link or a mailto:, so it's a + // relative URL + link := node.LinkData.Destination + if len(link) > 0 && !markup.IsLink(link) && + link[0] != '#' && !bytes.HasPrefix(link, byteMailto) && + node.LinkData.Footnote == nil { + lnk := string(link) + if r.IsWiki { + lnk = util.URLJoin("wiki", lnk) + } + link = []byte(util.URLJoin(r.URLPrefix, lnk)) + } + node.LinkData.Destination = link + return r.Renderer.RenderNode(w, node, entering) + case blackfriday.Text: + isListItem := false + for n := node.Parent; n != nil; n = n.Parent { + if n.Type == blackfriday.Item { + isListItem = true + break + } + } + if isListItem { + text := node.Literal + switch { + case bytes.HasPrefix(text, []byte("[ ] ")): + _, _ = w.Write([]byte(``)) + text = text[3:] + case bytes.HasPrefix(text, []byte("[x] ")): + _, _ = w.Write([]byte(``)) + text = text[3:] + } + node.Literal = text } } - r.Renderer.ListItem(out, text, flags) -} - -// Image defines how images should be processed to produce corresponding HTML elements. -func (r *Renderer) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) { - prefix := r.URLPrefix - if r.IsWiki { - prefix = util.URLJoin(prefix, "wiki", "raw") - } - prefix = strings.Replace(prefix, "/src/", "/media/", 1) - if len(link) > 0 && !markup.IsLink(link) { - lnk := string(link) - lnk = util.URLJoin(prefix, lnk) - lnk = strings.Replace(lnk, " ", "+", -1) - link = []byte(lnk) - } - - // Put a link around it pointing to itself by default - out.WriteString(``) - r.Renderer.Image(out, link, title, alt) - out.WriteString("") + return r.Renderer.RenderNode(w, node, entering) } const ( blackfridayExtensions = 0 | - blackfriday.EXTENSION_NO_INTRA_EMPHASIS | - blackfriday.EXTENSION_TABLES | - blackfriday.EXTENSION_FENCED_CODE | - blackfriday.EXTENSION_STRIKETHROUGH | - blackfriday.EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK | - blackfriday.EXTENSION_DEFINITION_LISTS | - blackfriday.EXTENSION_FOOTNOTES | - blackfriday.EXTENSION_HEADER_IDS | - blackfriday.EXTENSION_AUTO_HEADER_IDS + blackfriday.NoIntraEmphasis | + blackfriday.Tables | + blackfriday.FencedCode | + blackfriday.Strikethrough | + blackfriday.NoEmptyLineBeforeBlock | + blackfriday.DefinitionLists | + blackfriday.Footnotes | + blackfriday.HeadingIDs | + blackfriday.AutoHeadingIDs blackfridayHTMLFlags = 0 | - blackfriday.HTML_SKIP_STYLE | - blackfriday.HTML_OMIT_CONTENTS | - blackfriday.HTML_USE_SMARTYPANTS + blackfriday.Smartypants ) // RenderRaw renders Markdown to HTML without handling special links. func RenderRaw(body []byte, urlPrefix string, wikiMarkdown bool) []byte { renderer := &Renderer{ - Renderer: blackfriday.HtmlRenderer(blackfridayHTMLFlags, "", ""), + Renderer: blackfriday.NewHTMLRenderer(blackfriday.HTMLRendererParameters{ + Flags: blackfridayHTMLFlags, + }), URLPrefix: urlPrefix, IsWiki: wikiMarkdown, } exts := blackfridayExtensions if setting.Markdown.EnableHardLineBreak { - exts |= blackfriday.EXTENSION_HARD_LINE_BREAK + exts |= blackfriday.HardLineBreak } - body = blackfriday.Markdown(body, renderer, exts) + body = blackfriday.Run(body, blackfriday.WithRenderer(renderer), blackfriday.WithExtensions(exts)) return markup.SanitizeBytes(body) } diff --git a/modules/markup/markdown/markdown_test.go b/modules/markup/markdown/markdown_test.go index 669b49367e..b29f870ce5 100644 --- a/modules/markup/markdown/markdown_test.go +++ b/modules/markup/markdown/markdown_test.go @@ -166,13 +166,13 @@ func testAnswers(baseURLContent, baseURLImages string) []string {

Footnotes

Here is a simple footnote,1 and here is a longer one.2

+

    -
  1. This is the first footnote. -
  2. +
  3. This is the first footnote.
  4. Here is one with multiple paragraphs and code.

    @@ -180,9 +180,9 @@ func testAnswers(baseURLContent, baseURLImages string) []string {

    { my code }

    -

    Add as many paragraphs as you like.

    -
  5. +

    Add as many paragraphs as you like.

+
`, } diff --git a/modules/markup/mdstripper/mdstripper.go b/modules/markup/mdstripper/mdstripper.go index 7a901b17a9..d248944b68 100644 --- a/modules/markup/mdstripper/mdstripper.go +++ b/modules/markup/mdstripper/mdstripper.go @@ -6,43 +6,39 @@ package mdstripper import ( "bytes" + "io" - "github.com/russross/blackfriday" + "github.com/russross/blackfriday/v2" ) // MarkdownStripper extends blackfriday.Renderer type MarkdownStripper struct { - blackfriday.Renderer links []string coallesce bool + empty bool } const ( blackfridayExtensions = 0 | - blackfriday.EXTENSION_NO_INTRA_EMPHASIS | - blackfriday.EXTENSION_TABLES | - blackfriday.EXTENSION_FENCED_CODE | - blackfriday.EXTENSION_STRIKETHROUGH | - blackfriday.EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK | - blackfriday.EXTENSION_DEFINITION_LISTS | - blackfriday.EXTENSION_FOOTNOTES | - blackfriday.EXTENSION_HEADER_IDS | - blackfriday.EXTENSION_AUTO_HEADER_IDS | + blackfriday.NoIntraEmphasis | + blackfriday.Tables | + blackfriday.FencedCode | + blackfriday.Strikethrough | + blackfriday.NoEmptyLineBeforeBlock | + blackfriday.DefinitionLists | + blackfriday.Footnotes | + blackfriday.HeadingIDs | + blackfriday.AutoHeadingIDs | // Not included in modules/markup/markdown/markdown.go; // required here to process inline links - blackfriday.EXTENSION_AUTOLINK + blackfriday.Autolink ) -//revive:disable:var-naming Implementing the Rendering interface requires breaking some linting rules - // StripMarkdown parses markdown content by removing all markup and code blocks // in order to extract links and other references func StripMarkdown(rawBytes []byte) (string, []string) { - stripper := &MarkdownStripper{ - links: make([]string, 0, 10), - } - body := blackfriday.Markdown(rawBytes, stripper, blackfridayExtensions) - return string(body), stripper.GetLinks() + buf, links := StripMarkdownBytes(rawBytes) + return string(buf), links } // StripMarkdownBytes parses markdown content by removing all markup and code blocks @@ -50,205 +46,67 @@ func StripMarkdown(rawBytes []byte) (string, []string) { func StripMarkdownBytes(rawBytes []byte) ([]byte, []string) { stripper := &MarkdownStripper{ links: make([]string, 0, 10), + empty: true, } - body := blackfriday.Markdown(rawBytes, stripper, blackfridayExtensions) - return body, stripper.GetLinks() + + parser := blackfriday.New(blackfriday.WithRenderer(stripper), blackfriday.WithExtensions(blackfridayExtensions)) + ast := parser.Parse(rawBytes) + var buf bytes.Buffer + stripper.RenderHeader(&buf, ast) + ast.Walk(func(node *blackfriday.Node, entering bool) blackfriday.WalkStatus { + return stripper.RenderNode(&buf, node, entering) + }) + stripper.RenderFooter(&buf, ast) + return buf.Bytes(), stripper.GetLinks() } -// block-level callbacks - -// BlockCode dummy function to proceed with rendering -func (r *MarkdownStripper) BlockCode(out *bytes.Buffer, text []byte, infoString string) { - // Not rendered +// RenderNode is the main rendering method. It will be called once for +// every leaf node and twice for every non-leaf node (first with +// entering=true, then with entering=false). The method should write its +// rendition of the node to the supplied writer w. +func (r *MarkdownStripper) RenderNode(w io.Writer, node *blackfriday.Node, entering bool) blackfriday.WalkStatus { + if !entering { + return blackfriday.GoToNext + } + switch node.Type { + case blackfriday.Text: + r.processString(w, node.Literal, node.Parent == nil) + return blackfriday.GoToNext + case blackfriday.Link: + r.processLink(w, node.LinkData.Destination) + r.coallesce = false + return blackfriday.SkipChildren + } r.coallesce = false + return blackfriday.GoToNext } -// BlockQuote dummy function to proceed with rendering -func (r *MarkdownStripper) BlockQuote(out *bytes.Buffer, text []byte) { - // FIXME: perhaps it's better to leave out block quote for this? - r.processString(out, text, false) +// RenderHeader is a method that allows the renderer to produce some +// content preceding the main body of the output document. +func (r *MarkdownStripper) RenderHeader(w io.Writer, ast *blackfriday.Node) { } -// BlockHtml dummy function to proceed with rendering -func (r *MarkdownStripper) BlockHtml(out *bytes.Buffer, text []byte) { //nolint - // Not rendered - r.coallesce = false +// RenderFooter is a symmetric counterpart of RenderHeader. +func (r *MarkdownStripper) RenderFooter(w io.Writer, ast *blackfriday.Node) { } -// Header dummy function to proceed with rendering -func (r *MarkdownStripper) Header(out *bytes.Buffer, text func() bool, level int, id string) { - text() - r.coallesce = false -} - -// HRule dummy function to proceed with rendering -func (r *MarkdownStripper) HRule(out *bytes.Buffer) { - // Not rendered - r.coallesce = false -} - -// List dummy function to proceed with rendering -func (r *MarkdownStripper) List(out *bytes.Buffer, text func() bool, flags int) { - text() - r.coallesce = false -} - -// ListItem dummy function to proceed with rendering -func (r *MarkdownStripper) ListItem(out *bytes.Buffer, text []byte, flags int) { - r.processString(out, text, false) -} - -// Paragraph dummy function to proceed with rendering -func (r *MarkdownStripper) Paragraph(out *bytes.Buffer, text func() bool) { - text() - r.coallesce = false -} - -// Table dummy function to proceed with rendering -func (r *MarkdownStripper) Table(out *bytes.Buffer, header []byte, body []byte, columnData []int) { - r.processString(out, header, false) - r.processString(out, body, false) -} - -// TableRow dummy function to proceed with rendering -func (r *MarkdownStripper) TableRow(out *bytes.Buffer, text []byte) { - r.processString(out, text, false) -} - -// TableHeaderCell dummy function to proceed with rendering -func (r *MarkdownStripper) TableHeaderCell(out *bytes.Buffer, text []byte, flags int) { - r.processString(out, text, false) -} - -// TableCell dummy function to proceed with rendering -func (r *MarkdownStripper) TableCell(out *bytes.Buffer, text []byte, flags int) { - r.processString(out, text, false) -} - -// Footnotes dummy function to proceed with rendering -func (r *MarkdownStripper) Footnotes(out *bytes.Buffer, text func() bool) { - text() -} - -// FootnoteItem dummy function to proceed with rendering -func (r *MarkdownStripper) FootnoteItem(out *bytes.Buffer, name, text []byte, flags int) { - r.processString(out, text, false) -} - -// TitleBlock dummy function to proceed with rendering -func (r *MarkdownStripper) TitleBlock(out *bytes.Buffer, text []byte) { - r.processString(out, text, false) -} - -// Span-level callbacks - -// AutoLink dummy function to proceed with rendering -func (r *MarkdownStripper) AutoLink(out *bytes.Buffer, link []byte, kind int) { - r.processLink(out, link, []byte{}) -} - -// CodeSpan dummy function to proceed with rendering -func (r *MarkdownStripper) CodeSpan(out *bytes.Buffer, text []byte) { - // Not rendered - r.coallesce = false -} - -// DoubleEmphasis dummy function to proceed with rendering -func (r *MarkdownStripper) DoubleEmphasis(out *bytes.Buffer, text []byte) { - r.processString(out, text, false) -} - -// Emphasis dummy function to proceed with rendering -func (r *MarkdownStripper) Emphasis(out *bytes.Buffer, text []byte) { - r.processString(out, text, false) -} - -// Image dummy function to proceed with rendering -func (r *MarkdownStripper) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) { - // Not rendered - r.coallesce = false -} - -// LineBreak dummy function to proceed with rendering -func (r *MarkdownStripper) LineBreak(out *bytes.Buffer) { - // Not rendered - r.coallesce = false -} - -// Link dummy function to proceed with rendering -func (r *MarkdownStripper) Link(out *bytes.Buffer, link []byte, title []byte, content []byte) { - r.processLink(out, link, content) -} - -// RawHtmlTag dummy function to proceed with rendering -func (r *MarkdownStripper) RawHtmlTag(out *bytes.Buffer, tag []byte) { //nolint - // Not rendered - r.coallesce = false -} - -// TripleEmphasis dummy function to proceed with rendering -func (r *MarkdownStripper) TripleEmphasis(out *bytes.Buffer, text []byte) { - r.processString(out, text, false) -} - -// StrikeThrough dummy function to proceed with rendering -func (r *MarkdownStripper) StrikeThrough(out *bytes.Buffer, text []byte) { - r.processString(out, text, false) -} - -// FootnoteRef dummy function to proceed with rendering -func (r *MarkdownStripper) FootnoteRef(out *bytes.Buffer, ref []byte, id int) { - // Not rendered - r.coallesce = false -} - -// Low-level callbacks - -// Entity dummy function to proceed with rendering -func (r *MarkdownStripper) Entity(out *bytes.Buffer, entity []byte) { - // FIXME: literal entities are not parsed; perhaps they should - r.coallesce = false -} - -// NormalText dummy function to proceed with rendering -func (r *MarkdownStripper) NormalText(out *bytes.Buffer, text []byte) { - r.processString(out, text, true) -} - -// Header and footer - -// DocumentHeader dummy function to proceed with rendering -func (r *MarkdownStripper) DocumentHeader(out *bytes.Buffer) { - r.coallesce = false -} - -// DocumentFooter dummy function to proceed with rendering -func (r *MarkdownStripper) DocumentFooter(out *bytes.Buffer) { - r.coallesce = false -} - -// GetFlags returns rendering flags -func (r *MarkdownStripper) GetFlags() int { - return 0 -} - -//revive:enable:var-naming - -func doubleSpace(out *bytes.Buffer) { - if out.Len() > 0 { - out.WriteByte('\n') +func (r *MarkdownStripper) doubleSpace(w io.Writer) { + if !r.empty { + _, _ = w.Write([]byte{'\n'}) } } -func (r *MarkdownStripper) processString(out *bytes.Buffer, text []byte, coallesce bool) { +func (r *MarkdownStripper) processString(w io.Writer, text []byte, coallesce bool) { // Always break-up words if !coallesce || !r.coallesce { - doubleSpace(out) + r.doubleSpace(w) } - out.Write(text) + _, _ = w.Write(text) r.coallesce = coallesce + r.empty = false } -func (r *MarkdownStripper) processLink(out *bytes.Buffer, link []byte, content []byte) { + +func (r *MarkdownStripper) processLink(w io.Writer, link []byte) { // Links are processed out of band r.links = append(r.links, string(link)) r.coallesce = false diff --git a/modules/markup/orgmode/orgmode.go b/modules/markup/orgmode/orgmode.go index f63155201e..54188d2734 100644 --- a/modules/markup/orgmode/orgmode.go +++ b/modules/markup/orgmode/orgmode.go @@ -5,12 +5,16 @@ package markup import ( + "bytes" + "fmt" + "html" + "strings" + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup" - "code.gitea.io/gitea/modules/markup/markdown" + "code.gitea.io/gitea/modules/util" - "github.com/chaseadamsio/goorgeous" - "github.com/russross/blackfriday" + "github.com/niklasfasching/go-org/org" ) func init() { @@ -32,23 +36,23 @@ func (Parser) Extensions() []string { } // Render renders orgmode rawbytes to HTML -func Render(rawBytes []byte, urlPrefix string, metas map[string]string, isWiki bool) (result []byte) { - defer func() { - if err := recover(); err != nil { - log.Error("Panic in orgmode.Render: %v Just returning the rawBytes", err) - result = rawBytes - } - }() - htmlFlags := blackfriday.HTML_USE_XHTML - htmlFlags |= blackfriday.HTML_SKIP_STYLE - htmlFlags |= blackfriday.HTML_OMIT_CONTENTS - renderer := &markdown.Renderer{ - Renderer: blackfriday.HtmlRenderer(htmlFlags, "", ""), - URLPrefix: urlPrefix, - IsWiki: isWiki, +func Render(rawBytes []byte, urlPrefix string, metas map[string]string, isWiki bool) []byte { + htmlWriter := org.NewHTMLWriter() + + renderer := &Renderer{ + HTMLWriter: htmlWriter, + URLPrefix: urlPrefix, + IsWiki: isWiki, } - result = goorgeous.Org(rawBytes, renderer) - return + + htmlWriter.ExtendingWriter = renderer + + res, err := org.New().Silent().Parse(bytes.NewReader(rawBytes), "").Write(renderer) + if err != nil { + log.Error("Panic in orgmode.Render: %v Just returning the rawBytes", err) + return rawBytes + } + return []byte(res) } // RenderString reners orgmode string to HTML string @@ -56,7 +60,63 @@ func RenderString(rawContent string, urlPrefix string, metas map[string]string, return string(Render([]byte(rawContent), urlPrefix, metas, isWiki)) } -// Render implements markup.Parser +// Render reners orgmode string to HTML string func (Parser) Render(rawBytes []byte, urlPrefix string, metas map[string]string, isWiki bool) []byte { return Render(rawBytes, urlPrefix, metas, isWiki) } + +// Renderer implements org.Writer +type Renderer struct { + *org.HTMLWriter + URLPrefix string + IsWiki bool +} + +var byteMailto = []byte("mailto:") + +// WriteRegularLink renders images, links or videos +func (r *Renderer) WriteRegularLink(l org.RegularLink) { + link := []byte(html.EscapeString(l.URL)) + if l.Protocol == "file" { + link = link[len("file:"):] + } + if len(link) > 0 && !markup.IsLink(link) && + link[0] != '#' && !bytes.HasPrefix(link, byteMailto) { + lnk := string(link) + if r.IsWiki { + lnk = util.URLJoin("wiki", lnk) + } + link = []byte(util.URLJoin(r.URLPrefix, lnk)) + } + + description := string(link) + if l.Description != nil { + description = r.nodesAsString(l.Description...) + } + switch l.Kind() { + case "image": + r.WriteString(fmt.Sprintf(`%s`, link, description, description)) + case "video": + r.WriteString(fmt.Sprintf(``, link, description, description)) + default: + r.WriteString(fmt.Sprintf(`%s`, link, description, description)) + } +} + +func (r *Renderer) emptyClone() *Renderer { + wcopy := *(r.HTMLWriter) + wcopy.Builder = strings.Builder{} + + rcopy := *r + rcopy.HTMLWriter = &wcopy + + wcopy.ExtendingWriter = &rcopy + + return &rcopy +} + +func (r *Renderer) nodesAsString(nodes ...org.Node) string { + tmp := r.emptyClone() + org.WriteNodes(tmp, nodes...) + return tmp.String() +} diff --git a/modules/markup/orgmode/orgmode_test.go b/modules/markup/orgmode/orgmode_test.go index 3846922c25..40323912b4 100644 --- a/modules/markup/orgmode/orgmode_test.go +++ b/modules/markup/orgmode/orgmode_test.go @@ -27,12 +27,12 @@ func TestRender_StandardLinks(t *testing.T) { assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer)) } - googleRendered := `

https://google.com/

` + googleRendered := "

\nhttps://google.com/\n

" test("[[https://google.com/]]", googleRendered) lnk := util.URLJoin(AppSubURL, "WikiPage") test("[[WikiPage][WikiPage]]", - `

WikiPage

`) + "

\nWikiPage\n

") } func TestRender_Images(t *testing.T) { @@ -45,10 +45,8 @@ func TestRender_Images(t *testing.T) { } url := "../../.images/src/02/train.jpg" - title := "Train" result := util.URLJoin(AppSubURL, url) - test( - "[[file:"+url+"]["+title+"]]", - `

`+title+`

`) + test("[[file:"+url+"]]", + "

\n\""+result+"\"\n

") } diff --git a/vendor/github.com/chaseadamsio/goorgeous/.gitignore b/vendor/github.com/chaseadamsio/goorgeous/.gitignore deleted file mode 100644 index 496ee2ca6a..0000000000 --- a/vendor/github.com/chaseadamsio/goorgeous/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.DS_Store \ No newline at end of file diff --git a/vendor/github.com/chaseadamsio/goorgeous/.travis.yml b/vendor/github.com/chaseadamsio/goorgeous/.travis.yml deleted file mode 100644 index 31dca02817..0000000000 --- a/vendor/github.com/chaseadamsio/goorgeous/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -language: go - -go: - - 1.7 - -before_install: - - go get golang.org/x/tools/cmd/cover - - go get github.com/mattn/goveralls - -script: - - go test -v -covermode=count -coverprofile=coverage.out - - $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci diff --git a/vendor/github.com/chaseadamsio/goorgeous/README.org b/vendor/github.com/chaseadamsio/goorgeous/README.org deleted file mode 100644 index 37e0f2ec73..0000000000 --- a/vendor/github.com/chaseadamsio/goorgeous/README.org +++ /dev/null @@ -1,66 +0,0 @@ -#+TITLE: chaseadamsio/goorgeous - -[[https://travis-ci.org/chaseadamsio/goorgeous.svg?branch=master]] -[[https://coveralls.io/repos/github/chaseadamsio/goorgeous/badge.svg?branch=master]] - -/goorgeous is a Go Org to HTML Parser./ - -[[file:gopher_small.gif]] - -*Pronounced: Go? Org? Yes!* - -#+BEGIN_QUOTE -"Org mode is for keeping notes, maintaining TODO lists, planning projects, and authoring documents with a fast and effective plain-text system." - -- [[orgmode.org]] -#+END_QUOTE - -The purpose of this package is to come as close as possible as parsing an =*.org= document into HTML, the same way one might publish [[http://orgmode.org/worg/org-tutorials/org-publish-html-tutorial.html][with org-publish-html from Emacs]]. - -* Installation - -#+BEGIN_SRC sh - go get -u github.com/chaseadamsio/goorgeous -#+END_SRC - -* Usage - -** Org Headers - -To retrieve the headers from a =[]byte=, call =OrgHeaders= and it will return a =map[string]interface{}=: - -#+BEGIN_SRC go - input := "#+title: goorgeous\n* Some Headline\n" - out := goorgeous.OrgHeaders(input) -#+END_SRC - -#+BEGIN_SRC go - map[string]interface{}{ - "title": "goorgeous" - } -#+END_SRC - -** Org Content - -After importing =github.com/chaseadamsio/goorgeous=, you can call =Org= with a =[]byte= and it will return an =html= version of the content as a =[]byte= - -#+BEGIN_SRC go - input := "#+TITLE: goorgeous\n* Some Headline\n" - out := goorgeous.Org(input) -#+END_SRC - -=out= will be: - -#+BEGIN_SRC html -

Some Headline

/n -#+END_SRC - -* Why? - -First off, I've become an unapologetic user of Emacs & ever since finding =org-mode= I use it for anything having to do with writing content, organizing my life and keeping documentation of my days/weeks/months. - -Although I like Emacs & =emacs-lisp=, I publish all of my html sites with [[https://gohugo.io][Hugo Static Site Generator]] and wanted to be able to write my content in =org-mode= in Emacs rather than markdown. - -Hugo's implementation of templating and speed are unmatched, so the only way I knew for sure I could continue to use Hugo and write in =org-mode= seamlessly was to write a golang parser for org content and submit a PR for Hugo to use it. -* Acknowledgements -I leaned heavily on russross' [[https://github.com/russross/blackfriday][blackfriday markdown renderer]] as both an example of how to write a parser (with some updates to leverage the go we know today) and reusing the blackfriday HTML Renderer so I didn't have to write my own! diff --git a/vendor/github.com/chaseadamsio/goorgeous/goorgeous.go b/vendor/github.com/chaseadamsio/goorgeous/goorgeous.go deleted file mode 100644 index f1b2671d65..0000000000 --- a/vendor/github.com/chaseadamsio/goorgeous/goorgeous.go +++ /dev/null @@ -1,803 +0,0 @@ -package goorgeous - -import ( - "bufio" - "bytes" - "regexp" - - "github.com/russross/blackfriday" - "github.com/shurcooL/sanitized_anchor_name" -) - -type inlineParser func(p *parser, out *bytes.Buffer, data []byte, offset int) int - -type footnotes struct { - id string - def string -} - -type parser struct { - r blackfriday.Renderer - inlineCallback [256]inlineParser - notes []footnotes -} - -// NewParser returns a new parser with the inlineCallbacks required for org content -func NewParser(renderer blackfriday.Renderer) *parser { - p := new(parser) - p.r = renderer - - p.inlineCallback['='] = generateVerbatim - p.inlineCallback['~'] = generateCode - p.inlineCallback['/'] = generateEmphasis - p.inlineCallback['_'] = generateUnderline - p.inlineCallback['*'] = generateBold - p.inlineCallback['+'] = generateStrikethrough - p.inlineCallback['['] = generateLinkOrImg - - return p -} - -// OrgCommon is the easiest way to parse a byte slice of org content and makes assumptions -// that the caller wants to use blackfriday's HTMLRenderer with XHTML -func OrgCommon(input []byte) []byte { - renderer := blackfriday.HtmlRenderer(blackfriday.HTML_USE_XHTML, "", "") - return OrgOptions(input, renderer) -} - -// Org is a convenience name for OrgOptions -func Org(input []byte, renderer blackfriday.Renderer) []byte { - return OrgOptions(input, renderer) -} - -// OrgOptions takes an org content byte slice and a renderer to use -func OrgOptions(input []byte, renderer blackfriday.Renderer) []byte { - // in the case that we need to render something in isEmpty but there isn't a new line char - input = append(input, '\n') - var output bytes.Buffer - - p := NewParser(renderer) - - scanner := bufio.NewScanner(bytes.NewReader(input)) - // used to capture code blocks - marker := "" - syntax := "" - listType := "" - inParagraph := false - inList := false - inTable := false - inFixedWidthArea := false - var tmpBlock bytes.Buffer - - for scanner.Scan() { - data := scanner.Bytes() - - if !isEmpty(data) && isComment(data) || IsKeyword(data) { - switch { - case inList: - if tmpBlock.Len() > 0 { - p.generateList(&output, tmpBlock.Bytes(), listType) - } - inList = false - listType = "" - tmpBlock.Reset() - case inTable: - if tmpBlock.Len() > 0 { - p.generateTable(&output, tmpBlock.Bytes()) - } - inTable = false - tmpBlock.Reset() - case inParagraph: - if tmpBlock.Len() > 0 { - p.generateParagraph(&output, tmpBlock.Bytes()[:len(tmpBlock.Bytes())-1]) - } - inParagraph = false - tmpBlock.Reset() - case inFixedWidthArea: - if tmpBlock.Len() > 0 { - tmpBlock.WriteString("\n") - output.Write(tmpBlock.Bytes()) - } - inFixedWidthArea = false - tmpBlock.Reset() - } - - } - - switch { - case isEmpty(data): - switch { - case inList: - if tmpBlock.Len() > 0 { - p.generateList(&output, tmpBlock.Bytes(), listType) - } - inList = false - listType = "" - tmpBlock.Reset() - case inTable: - if tmpBlock.Len() > 0 { - p.generateTable(&output, tmpBlock.Bytes()) - } - inTable = false - tmpBlock.Reset() - case inParagraph: - if tmpBlock.Len() > 0 { - p.generateParagraph(&output, tmpBlock.Bytes()[:len(tmpBlock.Bytes())-1]) - } - inParagraph = false - tmpBlock.Reset() - case inFixedWidthArea: - if tmpBlock.Len() > 0 { - tmpBlock.WriteString("\n") - output.Write(tmpBlock.Bytes()) - } - inFixedWidthArea = false - tmpBlock.Reset() - case marker != "": - tmpBlock.WriteByte('\n') - default: - continue - } - case isPropertyDrawer(data) || marker == "PROPERTIES": - if marker == "" { - marker = "PROPERTIES" - } - if bytes.Equal(data, []byte(":END:")) { - marker = "" - } - continue - case isBlock(data) || marker != "": - matches := reBlock.FindSubmatch(data) - if len(matches) > 0 { - if string(matches[1]) == "END" { - switch marker { - case "QUOTE": - var tmpBuf bytes.Buffer - p.inline(&tmpBuf, tmpBlock.Bytes()) - p.r.BlockQuote(&output, tmpBuf.Bytes()) - case "CENTER": - var tmpBuf bytes.Buffer - output.WriteString("
\n") - p.inline(&tmpBuf, tmpBlock.Bytes()) - output.Write(tmpBuf.Bytes()) - output.WriteString("
\n") - default: - tmpBlock.WriteByte('\n') - p.r.BlockCode(&output, tmpBlock.Bytes(), syntax) - } - marker = "" - tmpBlock.Reset() - continue - } - - } - if marker != "" { - if marker != "SRC" && marker != "EXAMPLE" { - var tmpBuf bytes.Buffer - tmpBuf.Write([]byte("

\n")) - p.inline(&tmpBuf, data) - tmpBuf.WriteByte('\n') - tmpBuf.Write([]byte("

\n")) - tmpBlock.Write(tmpBuf.Bytes()) - - } else { - tmpBlock.WriteByte('\n') - tmpBlock.Write(data) - } - - } else { - marker = string(matches[2]) - syntax = string(matches[3]) - } - case isFootnoteDef(data): - matches := reFootnoteDef.FindSubmatch(data) - for i := range p.notes { - if p.notes[i].id == string(matches[1]) { - p.notes[i].def = string(matches[2]) - } - } - case isTable(data): - if inTable != true { - inTable = true - } - tmpBlock.Write(data) - tmpBlock.WriteByte('\n') - case IsKeyword(data): - continue - case isComment(data): - p.generateComment(&output, data) - case isHeadline(data): - p.generateHeadline(&output, data) - case isDefinitionList(data): - if inList != true { - listType = "dl" - inList = true - } - var work bytes.Buffer - flags := blackfriday.LIST_TYPE_DEFINITION - matches := reDefinitionList.FindSubmatch(data) - flags |= blackfriday.LIST_TYPE_TERM - p.inline(&work, matches[1]) - p.r.ListItem(&tmpBlock, work.Bytes(), flags) - work.Reset() - flags &= ^blackfriday.LIST_TYPE_TERM - p.inline(&work, matches[2]) - p.r.ListItem(&tmpBlock, work.Bytes(), flags) - case isUnorderedList(data): - if inList != true { - listType = "ul" - inList = true - } - matches := reUnorderedList.FindSubmatch(data) - var work bytes.Buffer - p.inline(&work, matches[2]) - p.r.ListItem(&tmpBlock, work.Bytes(), 0) - case isOrderedList(data): - if inList != true { - listType = "ol" - inList = true - } - matches := reOrderedList.FindSubmatch(data) - var work bytes.Buffer - tmpBlock.WriteString(" 0 { - tmpBlock.WriteString(" value=\"") - tmpBlock.Write(matches[2]) - tmpBlock.WriteString("\"") - matches[3] = matches[3][1:] - } - p.inline(&work, matches[3]) - tmpBlock.WriteString(">") - tmpBlock.Write(work.Bytes()) - tmpBlock.WriteString("\n") - case isHorizontalRule(data): - p.r.HRule(&output) - case isExampleLine(data): - if inParagraph == true { - if len(tmpBlock.Bytes()) > 0 { - p.generateParagraph(&output, tmpBlock.Bytes()[:len(tmpBlock.Bytes())-1]) - inParagraph = false - } - tmpBlock.Reset() - } - if inFixedWidthArea != true { - tmpBlock.WriteString("
\n")
-				inFixedWidthArea = true
-			}
-			matches := reExampleLine.FindSubmatch(data)
-			tmpBlock.Write(matches[1])
-			tmpBlock.WriteString("\n")
-			break
-		default:
-			if inParagraph == false {
-				inParagraph = true
-				if inFixedWidthArea == true {
-					if tmpBlock.Len() > 0 {
-						tmpBlock.WriteString("
") - output.Write(tmpBlock.Bytes()) - } - inFixedWidthArea = false - tmpBlock.Reset() - } - } - tmpBlock.Write(data) - tmpBlock.WriteByte('\n') - } - } - - if len(tmpBlock.Bytes()) > 0 { - if inParagraph == true { - p.generateParagraph(&output, tmpBlock.Bytes()[:len(tmpBlock.Bytes())-1]) - } else if inFixedWidthArea == true { - tmpBlock.WriteString("\n") - output.Write(tmpBlock.Bytes()) - } - } - - // Writing footnote def. list - if len(p.notes) > 0 { - flags := blackfriday.LIST_ITEM_BEGINNING_OF_LIST - p.r.Footnotes(&output, func() bool { - for i := range p.notes { - p.r.FootnoteItem(&output, []byte(p.notes[i].id), []byte(p.notes[i].def), flags) - } - return true - }) - } - - return output.Bytes() -} - -// Org Syntax has been broken up into 4 distinct sections based on -// the org-syntax draft (http://orgmode.org/worg/dev/org-syntax.html): -// - Headlines -// - Greater Elements -// - Elements -// - Objects - -// Headlines -func isHeadline(data []byte) bool { - if !charMatches(data[0], '*') { - return false - } - level := 0 - for level < 6 && charMatches(data[level], '*') { - level++ - } - return charMatches(data[level], ' ') -} - -func (p *parser) generateHeadline(out *bytes.Buffer, data []byte) { - level := 1 - status := "" - priority := "" - - for level < 6 && data[level] == '*' { - level++ - } - - start := skipChar(data, level, ' ') - - data = data[start:] - i := 0 - - // Check if has a status so it can be rendered as a separate span that can be hidden or - // modified with CSS classes - if hasStatus(data[i:4]) { - status = string(data[i:4]) - i += 5 // one extra character for the next whitespace - } - - // Check if the next byte is a priority marker - if data[i] == '[' && hasPriority(data[i+1]) { - priority = string(data[i+1]) - i += 4 // for "[c]" + ' ' - } - - tags, tagsFound := findTags(data, i) - - headlineID := sanitized_anchor_name.Create(string(data[i:])) - - generate := func() bool { - dataEnd := len(data) - if tagsFound > 0 { - dataEnd = tagsFound - } - - headline := bytes.TrimRight(data[i:dataEnd], " \t") - - if status != "" { - out.WriteString("" + status + "") - out.WriteByte(' ') - } - - if priority != "" { - out.WriteString("[" + priority + "]") - out.WriteByte(' ') - } - - p.inline(out, headline) - - if tagsFound > 0 { - for _, tag := range tags { - out.WriteByte(' ') - out.WriteString("" + tag + "") - out.WriteByte(' ') - } - } - return true - } - - p.r.Header(out, generate, level, headlineID) -} - -func hasStatus(data []byte) bool { - return bytes.Contains(data, []byte("TODO")) || bytes.Contains(data, []byte("DONE")) -} - -func hasPriority(char byte) bool { - return (charMatches(char, 'A') || charMatches(char, 'B') || charMatches(char, 'C')) -} - -func findTags(data []byte, start int) ([]string, int) { - tags := []string{} - tagOpener := 0 - tagMarker := tagOpener - for tIdx := start; tIdx < len(data); tIdx++ { - if tagMarker > 0 && data[tIdx] == ':' { - tags = append(tags, string(data[tagMarker+1:tIdx])) - tagMarker = tIdx - } - if data[tIdx] == ':' && tagOpener == 0 && data[tIdx-1] == ' ' { - tagMarker = tIdx - tagOpener = tIdx - } - } - return tags, tagOpener -} - -// Greater Elements -// ~~ Definition Lists -var reDefinitionList = regexp.MustCompile(`^\s*-\s+(.+?)\s+::\s+(.*)`) - -func isDefinitionList(data []byte) bool { - return reDefinitionList.Match(data) -} - -// ~~ Example lines -var reExampleLine = regexp.MustCompile(`^\s*:\s(\s*.*)|^\s*:$`) - -func isExampleLine(data []byte) bool { - return reExampleLine.Match(data) -} - -// ~~ Ordered Lists -var reOrderedList = regexp.MustCompile(`^(\s*)\d+\.\s+\[?@?(\d*)\]?(.+)`) - -func isOrderedList(data []byte) bool { - return reOrderedList.Match(data) -} - -// ~~ Unordered Lists -var reUnorderedList = regexp.MustCompile(`^(\s*)[-\+]\s+(.+)`) - -func isUnorderedList(data []byte) bool { - return reUnorderedList.Match(data) -} - -// ~~ Tables -var reTableHeaders = regexp.MustCompile(`^[|+-]*$`) - -func isTable(data []byte) bool { - return charMatches(data[0], '|') -} - -func (p *parser) generateTable(output *bytes.Buffer, data []byte) { - var table bytes.Buffer - rows := bytes.Split(bytes.Trim(data, "\n"), []byte("\n")) - hasTableHeaders := len(rows) > 1 - if len(rows) > 1 { - hasTableHeaders = reTableHeaders.Match(rows[1]) - } - tbodySet := false - - for idx, row := range rows { - var rowBuff bytes.Buffer - if hasTableHeaders && idx == 0 { - table.WriteString("") - for _, cell := range bytes.Split(row[1:len(row)-1], []byte("|")) { - p.r.TableHeaderCell(&rowBuff, bytes.Trim(cell, " \t"), 0) - } - p.r.TableRow(&table, rowBuff.Bytes()) - table.WriteString("\n") - } else if hasTableHeaders && idx == 1 { - continue - } else { - if !tbodySet { - table.WriteString("") - tbodySet = true - } - if !reTableHeaders.Match(row) { - for _, cell := range bytes.Split(row[1:len(row)-1], []byte("|")) { - var cellBuff bytes.Buffer - p.inline(&cellBuff, bytes.Trim(cell, " \t")) - p.r.TableCell(&rowBuff, cellBuff.Bytes(), 0) - } - p.r.TableRow(&table, rowBuff.Bytes()) - } - if tbodySet && idx == len(rows)-1 { - table.WriteString("\n") - tbodySet = false - } - } - } - - output.WriteString("\n\n") - output.Write(table.Bytes()) - output.WriteString("
\n") -} - -// ~~ Property Drawers - -func isPropertyDrawer(data []byte) bool { - return bytes.Equal(data, []byte(":PROPERTIES:")) -} - -// ~~ Dynamic Blocks -var reBlock = regexp.MustCompile(`^#\+(BEGIN|END)_(\w+)\s*([0-9A-Za-z_\-]*)?`) - -func isBlock(data []byte) bool { - return reBlock.Match(data) -} - -// ~~ Footnotes -var reFootnoteDef = regexp.MustCompile(`^\[fn:([\w]+)\] +(.+)`) - -func isFootnoteDef(data []byte) bool { - return reFootnoteDef.Match(data) -} - -// Elements -// ~~ Keywords -func IsKeyword(data []byte) bool { - return len(data) > 2 && charMatches(data[0], '#') && charMatches(data[1], '+') && !charMatches(data[2], ' ') -} - -// ~~ Comments -func isComment(data []byte) bool { - return charMatches(data[0], '#') && charMatches(data[1], ' ') -} - -func (p *parser) generateComment(out *bytes.Buffer, data []byte) { - var work bytes.Buffer - work.WriteString("") - work.WriteByte('\n') - out.Write(work.Bytes()) -} - -// ~~ Horizontal Rules -var reHorizontalRule = regexp.MustCompile(`^\s*?-----\s?$`) - -func isHorizontalRule(data []byte) bool { - return reHorizontalRule.Match(data) -} - -// ~~ Paragraphs -func (p *parser) generateParagraph(out *bytes.Buffer, data []byte) { - generate := func() bool { - p.inline(out, bytes.Trim(data, " ")) - return true - } - p.r.Paragraph(out, generate) -} - -func (p *parser) generateList(output *bytes.Buffer, data []byte, listType string) { - generateList := func() bool { - output.WriteByte('\n') - p.inline(output, bytes.Trim(data, " ")) - return true - } - switch listType { - case "ul": - p.r.List(output, generateList, 0) - case "ol": - p.r.List(output, generateList, blackfriday.LIST_TYPE_ORDERED) - case "dl": - p.r.List(output, generateList, blackfriday.LIST_TYPE_DEFINITION) - } -} - -// Objects - -func (p *parser) inline(out *bytes.Buffer, data []byte) { - i, end := 0, 0 - - for i < len(data) { - for end < len(data) && p.inlineCallback[data[end]] == nil { - end++ - } - - p.r.Entity(out, data[i:end]) - - if end >= len(data) { - break - } - i = end - - handler := p.inlineCallback[data[i]] - - if consumed := handler(p, out, data, i); consumed > 0 { - i += consumed - end = i - continue - } - - end = i + 1 - } -} - -func isAcceptablePreOpeningChar(dataIn, data []byte, offset int) bool { - if len(dataIn) == len(data) { - return true - } - - char := dataIn[offset-1] - return charMatches(char, ' ') || isPreChar(char) -} - -func isPreChar(char byte) bool { - return charMatches(char, '>') || charMatches(char, '(') || charMatches(char, '{') || charMatches(char, '[') -} - -func isAcceptablePostClosingChar(char byte) bool { - return charMatches(char, ' ') || isTerminatingChar(char) -} - -func isTerminatingChar(char byte) bool { - return charMatches(char, '.') || charMatches(char, ',') || charMatches(char, '?') || charMatches(char, '!') || charMatches(char, ')') || charMatches(char, '}') || charMatches(char, ']') -} - -func findLastCharInInline(data []byte, char byte) int { - timesFound := 0 - last := 0 - // Start from character after the inline indicator - for i := 1; i < len(data); i++ { - if timesFound == 1 { - break - } - if data[i] == char { - if len(data) == i+1 || (len(data) > i+1 && isAcceptablePostClosingChar(data[i+1])) { - last = i - timesFound += 1 - } - } - } - return last -} - -func generator(p *parser, out *bytes.Buffer, dataIn []byte, offset int, char byte, doInline bool, renderer func(*bytes.Buffer, []byte)) int { - data := dataIn[offset:] - c := byte(char) - start := 1 - i := start - if len(data) <= 1 { - return 0 - } - - lastCharInside := findLastCharInInline(data, c) - - // Org mode spec says a non-whitespace character must immediately follow. - // if the current char is the marker, then there's no text between, not a candidate - if isSpace(data[i]) || lastCharInside == i || !isAcceptablePreOpeningChar(dataIn, data, offset) { - return 0 - } - - if lastCharInside > 0 { - var work bytes.Buffer - if doInline { - p.inline(&work, data[start:lastCharInside]) - renderer(out, work.Bytes()) - } else { - renderer(out, data[start:lastCharInside]) - } - next := lastCharInside + 1 - return next - } - - return 0 -} - -// ~~ Text Markup -func generateVerbatim(p *parser, out *bytes.Buffer, data []byte, offset int) int { - return generator(p, out, data, offset, '=', false, p.r.CodeSpan) -} - -func generateCode(p *parser, out *bytes.Buffer, data []byte, offset int) int { - return generator(p, out, data, offset, '~', false, p.r.CodeSpan) -} - -func generateEmphasis(p *parser, out *bytes.Buffer, data []byte, offset int) int { - return generator(p, out, data, offset, '/', true, p.r.Emphasis) -} - -func generateUnderline(p *parser, out *bytes.Buffer, data []byte, offset int) int { - underline := func(out *bytes.Buffer, text []byte) { - out.WriteString("") - out.Write(text) - out.WriteString("") - } - - return generator(p, out, data, offset, '_', true, underline) -} - -func generateBold(p *parser, out *bytes.Buffer, data []byte, offset int) int { - return generator(p, out, data, offset, '*', true, p.r.DoubleEmphasis) -} - -func generateStrikethrough(p *parser, out *bytes.Buffer, data []byte, offset int) int { - return generator(p, out, data, offset, '+', true, p.r.StrikeThrough) -} - -// ~~ Images and Links (inc. Footnote) -var reLinkOrImg = regexp.MustCompile(`\[\[(.+?)\]\[?(.*?)\]?\]`) - -func generateLinkOrImg(p *parser, out *bytes.Buffer, data []byte, offset int) int { - data = data[offset+1:] - start := 1 - i := start - var hyperlink []byte - isImage := false - isFootnote := false - closedLink := false - hasContent := false - - if bytes.Equal(data[0:3], []byte("fn:")) { - isFootnote = true - } else if data[0] != '[' { - return 0 - } - - if bytes.Equal(data[1:6], []byte("file:")) { - isImage = true - } - - for i < len(data) { - currChar := data[i] - switch { - case charMatches(currChar, ']') && closedLink == false: - if isImage { - hyperlink = data[start+5 : i] - } else if isFootnote { - refid := data[start+2 : i] - if bytes.Equal(refid, bytes.Trim(refid, " ")) { - p.notes = append(p.notes, footnotes{string(refid), "DEFINITION NOT FOUND"}) - p.r.FootnoteRef(out, refid, len(p.notes)) - return i + 2 - } else { - return 0 - } - } else if bytes.Equal(data[i-4:i], []byte(".org")) { - orgStart := start - if bytes.Equal(data[orgStart:orgStart+2], []byte("./")) { - orgStart = orgStart + 1 - } - hyperlink = data[orgStart : i-4] - } else { - hyperlink = data[start:i] - } - closedLink = true - case charMatches(currChar, '['): - start = i + 1 - hasContent = true - case charMatches(currChar, ']') && closedLink == true && hasContent == true && isImage == true: - p.r.Image(out, hyperlink, data[start:i], data[start:i]) - return i + 3 - case charMatches(currChar, ']') && closedLink == true && hasContent == true: - var tmpBuf bytes.Buffer - p.inline(&tmpBuf, data[start:i]) - p.r.Link(out, hyperlink, tmpBuf.Bytes(), tmpBuf.Bytes()) - return i + 3 - case charMatches(currChar, ']') && closedLink == true && hasContent == false && isImage == true: - p.r.Image(out, hyperlink, hyperlink, hyperlink) - return i + 2 - case charMatches(currChar, ']') && closedLink == true && hasContent == false: - p.r.Link(out, hyperlink, hyperlink, hyperlink) - return i + 2 - } - i++ - } - - return 0 -} - -// Helpers -func skipChar(data []byte, start int, char byte) int { - i := start - for i < len(data) && charMatches(data[i], char) { - i++ - } - return i -} - -func isSpace(char byte) bool { - return charMatches(char, ' ') -} - -func isEmpty(data []byte) bool { - if len(data) == 0 { - return true - } - - for i := 0; i < len(data) && !charMatches(data[i], '\n'); i++ { - if !charMatches(data[i], ' ') && !charMatches(data[i], '\t') { - return false - } - } - return true -} - -func charMatches(a byte, b byte) bool { - return a == b -} diff --git a/vendor/github.com/chaseadamsio/goorgeous/gopher.gif b/vendor/github.com/chaseadamsio/goorgeous/gopher.gif deleted file mode 100644 index be7567e3cfd666ee40c56b1d808f97116c092053..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15232 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 vTwbHjFEt;&5pDgN=1cw&96@-xsG_RGKMSARK% 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 +Copyright (c) 2018 Niklas Fasching Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/github.com/niklasfasching/go-org/org/block.go b/vendor/github.com/niklasfasching/go-org/org/block.go new file mode 100644 index 0000000000..0e7a526243 --- /dev/null +++ b/vendor/github.com/niklasfasching/go-org/org/block.go @@ -0,0 +1,84 @@ +package org + +import ( + "regexp" + "strings" + "unicode" +) + +type Block struct { + Name string + Parameters []string + Children []Node +} + +type Example struct { + Children []Node +} + +var exampleLineRegexp = regexp.MustCompile(`^(\s*):(\s(.*)|\s*$)`) +var beginBlockRegexp = regexp.MustCompile(`(?i)^(\s*)#\+BEGIN_(\w+)(.*)`) +var endBlockRegexp = regexp.MustCompile(`(?i)^(\s*)#\+END_(\w+)`) + +func lexBlock(line string) (token, bool) { + if m := beginBlockRegexp.FindStringSubmatch(line); m != nil { + return token{"beginBlock", len(m[1]), strings.ToUpper(m[2]), m}, true + } else if m := endBlockRegexp.FindStringSubmatch(line); m != nil { + return token{"endBlock", len(m[1]), strings.ToUpper(m[2]), m}, true + } + return nilToken, false +} + +func lexExample(line string) (token, bool) { + if m := exampleLineRegexp.FindStringSubmatch(line); m != nil { + return token{"example", len(m[1]), m[3], m}, true + } + return nilToken, false +} + +func isRawTextBlock(name string) bool { return name == "SRC" || name == "EXAMPLE" || name == "EXPORT" } + +func (d *Document) parseBlock(i int, parentStop stopFn) (int, Node) { + t, start := d.tokens[i], i + name, parameters := t.content, strings.Fields(t.matches[3]) + trim := trimIndentUpTo(d.tokens[i].lvl) + stop := func(d *Document, i int) bool { + return i >= len(d.tokens) || (d.tokens[i].kind == "endBlock" && d.tokens[i].content == name) + } + block, i := Block{name, parameters, nil}, i+1 + if isRawTextBlock(name) { + rawText := "" + for ; !stop(d, i); i++ { + rawText += trim(d.tokens[i].matches[0]) + "\n" + } + block.Children = d.parseRawInline(rawText) + } else { + consumed, nodes := d.parseMany(i, stop) + block.Children = nodes + i += consumed + } + if i < len(d.tokens) && d.tokens[i].kind == "endBlock" && d.tokens[i].content == name { + return i + 1 - start, block + } + return 0, nil +} + +func (d *Document) parseExample(i int, parentStop stopFn) (int, Node) { + example, start := Example{}, i + for ; !parentStop(d, i) && d.tokens[i].kind == "example"; i++ { + example.Children = append(example.Children, Text{d.tokens[i].content, true}) + } + return i - start, example +} + +func trimIndentUpTo(max int) func(string) string { + return func(line string) string { + i := 0 + for ; i < len(line) && i < max && unicode.IsSpace(rune(line[i])); i++ { + } + return line[i:] + } +} + +func (n Example) String() string { return orgWriter.nodesAsString(n) } +func (n Block) String() string { return orgWriter.nodesAsString(n) } diff --git a/vendor/github.com/niklasfasching/go-org/org/document.go b/vendor/github.com/niklasfasching/go-org/org/document.go new file mode 100644 index 0000000000..e43eb626db --- /dev/null +++ b/vendor/github.com/niklasfasching/go-org/org/document.go @@ -0,0 +1,260 @@ +// Package org is an Org mode syntax processor. +// +// It parses plain text into an AST and can export it as HTML or pretty printed Org mode syntax. +// Further export formats can be defined using the Writer interface. +// +// You probably want to start with something like this: +// input := strings.NewReader("Your Org mode input") +// html, err := org.New().Parse(input, "./").Write(org.NewHTMLWriter()) +// if err != nil { +// log.Fatalf("Something went wrong: %s", err) +// } +// log.Print(html) +package org + +import ( + "bufio" + "fmt" + "io" + "io/ioutil" + "log" + "os" + "strings" +) + +type Configuration struct { + MaxEmphasisNewLines int // Maximum number of newlines inside an emphasis. See org-emphasis-regexp-components newline. + AutoLink bool // Try to convert text passages that look like hyperlinks into hyperlinks. + DefaultSettings map[string]string // Default values for settings that are overriden by setting the same key in BufferSettings. + Log *log.Logger // Log is used to print warnings during parsing. + ReadFile func(filename string) ([]byte, error) // ReadFile is used to read e.g. #+INCLUDE files. +} + +// Document contains the parsing results and a pointer to the Configuration. +type Document struct { + *Configuration + Path string // Path of the file containing the parse input - used to resolve relative paths during parsing (e.g. INCLUDE). + tokens []token + Nodes []Node + NamedNodes map[string]Node + Outline Outline // Outline is a Table Of Contents for the document and contains all sections (headline + content). + BufferSettings map[string]string // Settings contains all settings that were parsed from keywords. + Error error +} + +// Node represents a parsed node of the document. +type Node interface { + String() string // String returns the pretty printed Org mode string for the node (see OrgWriter). +} + +type lexFn = func(line string) (t token, ok bool) +type parseFn = func(*Document, int, stopFn) (int, Node) +type stopFn = func(*Document, int) bool + +type token struct { + kind string + lvl int + content string + matches []string +} + +var lexFns = []lexFn{ + lexHeadline, + lexDrawer, + lexBlock, + lexList, + lexTable, + lexHorizontalRule, + lexKeywordOrComment, + lexFootnoteDefinition, + lexExample, + lexText, +} + +var nilToken = token{"nil", -1, "", nil} +var orgWriter = NewOrgWriter() + +// New returns a new Configuration with (hopefully) sane defaults. +func New() *Configuration { + return &Configuration{ + AutoLink: true, + MaxEmphasisNewLines: 1, + DefaultSettings: map[string]string{ + "TODO": "TODO | DONE", + "EXCLUDE_TAGS": "noexport", + "OPTIONS": "toc:t <:t e:t f:t pri:t todo:t tags:t", + }, + Log: log.New(os.Stderr, "go-org: ", 0), + ReadFile: ioutil.ReadFile, + } +} + +// String returns the pretty printed Org mode string for the given nodes (see OrgWriter). +func String(nodes []Node) string { return orgWriter.nodesAsString(nodes...) } + +// Write is called after with an instance of the Writer interface to export a parsed Document into another format. +func (d *Document) Write(w Writer) (out string, err error) { + defer func() { + if recovered := recover(); recovered != nil { + err = fmt.Errorf("could not write output: %s", recovered) + } + }() + if d.Error != nil { + return "", d.Error + } else if d.Nodes == nil { + return "", fmt.Errorf("could not write output: parse was not called") + } + w.Before(d) + WriteNodes(w, d.Nodes...) + w.After(d) + return w.String(), err +} + +// Parse parses the input into an AST (and some other helpful fields like Outline). +// To allow method chaining, errors are stored in document.Error rather than being returned. +func (c *Configuration) Parse(input io.Reader, path string) (d *Document) { + outlineSection := &Section{} + d = &Document{ + Configuration: c, + Outline: Outline{outlineSection, outlineSection, 0}, + BufferSettings: map[string]string{}, + NamedNodes: map[string]Node{}, + Path: path, + } + defer func() { + if recovered := recover(); recovered != nil { + d.Error = fmt.Errorf("could not parse input: %v", recovered) + } + }() + if d.tokens != nil { + d.Error = fmt.Errorf("parse was called multiple times") + } + d.tokenize(input) + _, nodes := d.parseMany(0, func(d *Document, i int) bool { return i >= len(d.tokens) }) + d.Nodes = nodes + return d +} + +// Silent disables all logging of warnings during parsing. +func (c *Configuration) Silent() *Configuration { + c.Log = log.New(ioutil.Discard, "", 0) + return c +} + +func (d *Document) tokenize(input io.Reader) { + d.tokens = []token{} + scanner := bufio.NewScanner(input) + for scanner.Scan() { + d.tokens = append(d.tokens, tokenize(scanner.Text())) + } + if err := scanner.Err(); err != nil { + d.Error = fmt.Errorf("could not tokenize input: %s", err) + } +} + +// Get returns the value for key in BufferSettings or DefaultSettings if key does not exist in the former +func (d *Document) Get(key string) string { + if v, ok := d.BufferSettings[key]; ok { + return v + } + if v, ok := d.DefaultSettings[key]; ok { + return v + } + return "" +} + +// GetOption returns the value associated to the export option key +// Currently supported options: +// - < (export timestamps) +// - e (export org entities) +// - f (export footnotes) +// - toc (export table of content) +// - todo (export headline todo status) +// - pri (export headline priority) +// - tags (export headline tags) +// see https://orgmode.org/manual/Export-settings.html for more information +func (d *Document) GetOption(key string) bool { + get := func(settings map[string]string) string { + for _, field := range strings.Fields(settings["OPTIONS"]) { + if strings.HasPrefix(field, key+":") { + return field[len(key)+1:] + } + } + return "" + } + value := get(d.BufferSettings) + if value == "" { + value = get(d.DefaultSettings) + } + switch value { + case "t": + return true + case "nil": + return false + default: + d.Log.Printf("Bad value for export option %s (%s)", key, value) + return false + } +} + +func (d *Document) parseOne(i int, stop stopFn) (consumed int, node Node) { + switch d.tokens[i].kind { + case "unorderedList", "orderedList": + consumed, node = d.parseList(i, stop) + case "tableRow", "tableSeparator": + consumed, node = d.parseTable(i, stop) + case "beginBlock": + consumed, node = d.parseBlock(i, stop) + case "beginDrawer": + consumed, node = d.parseDrawer(i, stop) + case "text": + consumed, node = d.parseParagraph(i, stop) + case "example": + consumed, node = d.parseExample(i, stop) + case "horizontalRule": + consumed, node = d.parseHorizontalRule(i, stop) + case "comment": + consumed, node = d.parseComment(i, stop) + case "keyword": + consumed, node = d.parseKeyword(i, stop) + case "headline": + consumed, node = d.parseHeadline(i, stop) + case "footnoteDefinition": + consumed, node = d.parseFootnoteDefinition(i, stop) + } + + if consumed != 0 { + return consumed, node + } + d.Log.Printf("Could not parse token %#v: Falling back to treating it as plain text.", d.tokens[i]) + m := plainTextRegexp.FindStringSubmatch(d.tokens[i].matches[0]) + d.tokens[i] = token{"text", len(m[1]), m[2], m} + return d.parseOne(i, stop) +} + +func (d *Document) parseMany(i int, stop stopFn) (int, []Node) { + start, nodes := i, []Node{} + for i < len(d.tokens) && !stop(d, i) { + consumed, node := d.parseOne(i, stop) + i += consumed + nodes = append(nodes, node) + } + return i - start, nodes +} + +func (d *Document) addHeadline(headline *Headline) int { + current := &Section{Headline: headline} + d.Outline.last.add(current) + d.Outline.count++ + d.Outline.last = current + return d.Outline.count +} + +func tokenize(line string) token { + for _, lexFn := range lexFns { + if token, ok := lexFn(line); ok { + return token + } + } + panic(fmt.Sprintf("could not lex line: %s", line)) +} diff --git a/vendor/github.com/niklasfasching/go-org/org/drawer.go b/vendor/github.com/niklasfasching/go-org/org/drawer.go new file mode 100644 index 0000000000..8bb9974380 --- /dev/null +++ b/vendor/github.com/niklasfasching/go-org/org/drawer.go @@ -0,0 +1,97 @@ +package org + +import ( + "regexp" + "strings" +) + +type Drawer struct { + Name string + Children []Node +} + +type PropertyDrawer struct { + Properties [][]string +} + +var beginDrawerRegexp = regexp.MustCompile(`^(\s*):(\S+):\s*$`) +var endDrawerRegexp = regexp.MustCompile(`^(\s*):END:\s*$`) +var propertyRegexp = regexp.MustCompile(`^(\s*):(\S+):(\s+(.*)$|$)`) + +func lexDrawer(line string) (token, bool) { + if m := endDrawerRegexp.FindStringSubmatch(line); m != nil { + return token{"endDrawer", len(m[1]), "", m}, true + } else if m := beginDrawerRegexp.FindStringSubmatch(line); m != nil { + return token{"beginDrawer", len(m[1]), strings.ToUpper(m[2]), m}, true + } + return nilToken, false +} + +func (d *Document) parseDrawer(i int, parentStop stopFn) (int, Node) { + name := strings.ToUpper(d.tokens[i].content) + if name == "PROPERTIES" { + return d.parsePropertyDrawer(i, parentStop) + } + drawer, start := Drawer{Name: name}, i + i++ + stop := func(d *Document, i int) bool { + if parentStop(d, i) { + return true + } + kind := d.tokens[i].kind + return kind == "beginDrawer" || kind == "endDrawer" || kind == "headline" + } + for { + consumed, nodes := d.parseMany(i, stop) + i += consumed + drawer.Children = append(drawer.Children, nodes...) + if i < len(d.tokens) && d.tokens[i].kind == "beginDrawer" { + p := Paragraph{[]Node{Text{":" + d.tokens[i].content + ":", false}}} + drawer.Children = append(drawer.Children, p) + i++ + } else { + break + } + } + if i < len(d.tokens) && d.tokens[i].kind == "endDrawer" { + i++ + } + return i - start, drawer +} + +func (d *Document) parsePropertyDrawer(i int, parentStop stopFn) (int, Node) { + drawer, start := PropertyDrawer{}, i + i++ + stop := func(d *Document, i int) bool { + return parentStop(d, i) || (d.tokens[i].kind != "text" && d.tokens[i].kind != "beginDrawer") + } + for ; !stop(d, i); i++ { + m := propertyRegexp.FindStringSubmatch(d.tokens[i].matches[0]) + if m == nil { + return 0, nil + } + k, v := strings.ToUpper(m[2]), strings.TrimSpace(m[4]) + drawer.Properties = append(drawer.Properties, []string{k, v}) + } + if i < len(d.tokens) && d.tokens[i].kind == "endDrawer" { + i++ + } else { + return 0, nil + } + return i - start, drawer +} + +func (d *PropertyDrawer) Get(key string) (string, bool) { + if d == nil { + return "", false + } + for _, kvPair := range d.Properties { + if kvPair[0] == key { + return kvPair[1], true + } + } + return "", false +} + +func (n Drawer) String() string { return orgWriter.nodesAsString(n) } +func (n PropertyDrawer) String() string { return orgWriter.nodesAsString(n) } diff --git a/vendor/github.com/niklasfasching/go-org/org/footnote.go b/vendor/github.com/niklasfasching/go-org/org/footnote.go new file mode 100644 index 0000000000..660e244386 --- /dev/null +++ b/vendor/github.com/niklasfasching/go-org/org/footnote.go @@ -0,0 +1,35 @@ +package org + +import ( + "regexp" +) + +type FootnoteDefinition struct { + Name string + Children []Node + Inline bool +} + +var footnoteDefinitionRegexp = regexp.MustCompile(`^\[fn:([\w-]+)\](\s+(.+)|\s*$)`) + +func lexFootnoteDefinition(line string) (token, bool) { + if m := footnoteDefinitionRegexp.FindStringSubmatch(line); m != nil { + return token{"footnoteDefinition", 0, m[1], m}, true + } + return nilToken, false +} + +func (d *Document) parseFootnoteDefinition(i int, parentStop stopFn) (int, Node) { + start, name := i, d.tokens[i].content + d.tokens[i] = tokenize(d.tokens[i].matches[2]) + stop := func(d *Document, i int) bool { + return parentStop(d, i) || + (isSecondBlankLine(d, i) && i > start+1) || + d.tokens[i].kind == "headline" || d.tokens[i].kind == "footnoteDefinition" + } + consumed, nodes := d.parseMany(i, stop) + definition := FootnoteDefinition{name, nodes, false} + return consumed, definition +} + +func (n FootnoteDefinition) String() string { return orgWriter.nodesAsString(n) } diff --git a/vendor/github.com/niklasfasching/go-org/org/fuzz.go b/vendor/github.com/niklasfasching/go-org/org/fuzz.go new file mode 100644 index 0000000000..1e72b5ad92 --- /dev/null +++ b/vendor/github.com/niklasfasching/go-org/org/fuzz.go @@ -0,0 +1,27 @@ +// +build gofuzz + +package org + +import ( + "bytes" + "strings" +) + +// Fuzz function to be used by https://github.com/dvyukov/go-fuzz +func Fuzz(input []byte) int { + conf := New().Silent() + d := conf.Parse(bytes.NewReader(input), "") + orgOutput, err := d.Write(NewOrgWriter()) + if err != nil { + panic(err) + } + htmlOutputA, err := d.Write(NewHTMLWriter()) + if err != nil { + panic(err) + } + htmlOutputB, err := conf.Parse(strings.NewReader(orgOutput), "").Write(NewHTMLWriter()) + if htmlOutputA != htmlOutputB { + panic("rendered org results in different html than original input") + } + return 0 +} diff --git a/vendor/github.com/niklasfasching/go-org/org/headline.go b/vendor/github.com/niklasfasching/go-org/org/headline.go new file mode 100644 index 0000000000..23b986fbc8 --- /dev/null +++ b/vendor/github.com/niklasfasching/go-org/org/headline.go @@ -0,0 +1,101 @@ +package org + +import ( + "fmt" + "regexp" + "strings" + "unicode" +) + +type Outline struct { + *Section + last *Section + count int +} + +type Section struct { + Headline *Headline + Parent *Section + Children []*Section +} + +type Headline struct { + Index int + Lvl int + Status string + Priority string + Properties *PropertyDrawer + Title []Node + Tags []string + Children []Node +} + +var headlineRegexp = regexp.MustCompile(`^([*]+)\s+(.*)`) +var tagRegexp = regexp.MustCompile(`(.*?)\s+(:[A-Za-z0-9_@#%:]+:\s*$)`) + +func lexHeadline(line string) (token, bool) { + if m := headlineRegexp.FindStringSubmatch(line); m != nil { + return token{"headline", len(m[1]), m[2], m}, true + } + return nilToken, false +} + +func (d *Document) parseHeadline(i int, parentStop stopFn) (int, Node) { + t, headline := d.tokens[i], Headline{} + headline.Lvl = t.lvl + + headline.Index = d.addHeadline(&headline) + + text := t.content + todoKeywords := strings.FieldsFunc(d.Get("TODO"), func(r rune) bool { return unicode.IsSpace(r) || r == '|' }) + for _, k := range todoKeywords { + if strings.HasPrefix(text, k) && len(text) > len(k) && unicode.IsSpace(rune(text[len(k)])) { + headline.Status = k + text = text[len(k)+1:] + break + } + } + + if len(text) >= 4 && text[0:2] == "[#" && strings.Contains("ABC", text[2:3]) && text[3] == ']' { + headline.Priority = text[2:3] + text = strings.TrimSpace(text[4:]) + } + + if m := tagRegexp.FindStringSubmatch(text); m != nil { + text = m[1] + headline.Tags = strings.FieldsFunc(m[2], func(r rune) bool { return r == ':' }) + } + + headline.Title = d.parseInline(text) + + stop := func(d *Document, i int) bool { + return parentStop(d, i) || d.tokens[i].kind == "headline" && d.tokens[i].lvl <= headline.Lvl + } + consumed, nodes := d.parseMany(i+1, stop) + if len(nodes) > 0 { + if d, ok := nodes[0].(PropertyDrawer); ok { + headline.Properties = &d + nodes = nodes[1:] + } + } + headline.Children = nodes + return consumed + 1, headline +} + +func (h Headline) ID() string { + if customID, ok := h.Properties.Get("CUSTOM_ID"); ok { + return customID + } + return fmt.Sprintf("headline-%d", h.Index) +} + +func (parent *Section) add(current *Section) { + if parent.Headline == nil || parent.Headline.Lvl < current.Headline.Lvl { + parent.Children = append(parent.Children, current) + current.Parent = parent + } else { + parent.Parent.add(current) + } +} + +func (n Headline) String() string { return orgWriter.nodesAsString(n) } diff --git a/vendor/github.com/niklasfasching/go-org/org/html_entity.go b/vendor/github.com/niklasfasching/go-org/org/html_entity.go new file mode 100644 index 0000000000..484059b28d --- /dev/null +++ b/vendor/github.com/niklasfasching/go-org/org/html_entity.go @@ -0,0 +1,437 @@ +package org + +import "strings" + +var htmlEntityReplacer *strings.Replacer + +func init() { + htmlEntities = append(htmlEntities, + "---", "—", + "--", "–", + "...", "…", + ) + htmlEntityReplacer = strings.NewReplacer(htmlEntities...) +} + +/* +Generated & copied over using the following elisp +(Setting up go generate seems like a waste for now - I call YAGNI on that one) + +(insert (mapconcat + (lambda (entity) (concat "`\\" (car entity) "`, `" (nth 6 entity) "`")) ; entity -> utf8 + (remove-if-not 'listp org-entities) + ",\n")) +*/ +var htmlEntities = []string{ + `\Agrave`, `À`, + `\agrave`, `à`, + `\Aacute`, `Á`, + `\aacute`, `á`, + `\Acirc`, `Â`, + `\acirc`, `â`, + `\Amacr`, `Ã`, + `\amacr`, `ã`, + `\Atilde`, `Ã`, + `\atilde`, `ã`, + `\Auml`, `Ä`, + `\auml`, `ä`, + `\Aring`, `Å`, + `\AA`, `Å`, + `\aring`, `å`, + `\AElig`, `Æ`, + `\aelig`, `æ`, + `\Ccedil`, `Ç`, + `\ccedil`, `ç`, + `\Egrave`, `È`, + `\egrave`, `è`, + `\Eacute`, `É`, + `\eacute`, `é`, + `\Ecirc`, `Ê`, + `\ecirc`, `ê`, + `\Euml`, `Ë`, + `\euml`, `ë`, + `\Igrave`, `Ì`, + `\igrave`, `ì`, + `\Iacute`, `Í`, + `\iacute`, `í`, + `\Icirc`, `Î`, + `\icirc`, `î`, + `\Iuml`, `Ï`, + `\iuml`, `ï`, + `\Ntilde`, `Ñ`, + `\ntilde`, `ñ`, + `\Ograve`, `Ò`, + `\ograve`, `ò`, + `\Oacute`, `Ó`, + `\oacute`, `ó`, + `\Ocirc`, `Ô`, + `\ocirc`, `ô`, + `\Otilde`, `Õ`, + `\otilde`, `õ`, + `\Ouml`, `Ö`, + `\ouml`, `ö`, + `\Oslash`, `Ø`, + `\oslash`, `ø`, + `\OElig`, `Œ`, + `\oelig`, `œ`, + `\Scaron`, `Š`, + `\scaron`, `š`, + `\szlig`, `ß`, + `\Ugrave`, `Ù`, + `\ugrave`, `ù`, + `\Uacute`, `Ú`, + `\uacute`, `ú`, + `\Ucirc`, `Û`, + `\ucirc`, `û`, + `\Uuml`, `Ü`, + `\uuml`, `ü`, + `\Yacute`, `Ý`, + `\yacute`, `ý`, + `\Yuml`, `Ÿ`, + `\yuml`, `ÿ`, + `\fnof`, `ƒ`, + `\real`, `ℜ`, + `\image`, `ℑ`, + `\weierp`, `℘`, + `\ell`, `ℓ`, + `\imath`, `ı`, + `\jmath`, `ȷ`, + `\Alpha`, `Α`, + `\alpha`, `α`, + `\Beta`, `Β`, + `\beta`, `β`, + `\Gamma`, `Γ`, + `\gamma`, `γ`, + `\Delta`, `Δ`, + `\delta`, `δ`, + `\Epsilon`, `Ε`, + `\epsilon`, `ε`, + `\varepsilon`, `ε`, + `\Zeta`, `Ζ`, + `\zeta`, `ζ`, + `\Eta`, `Η`, + `\eta`, `η`, + `\Theta`, `Θ`, + `\theta`, `θ`, + `\thetasym`, `ϑ`, + `\vartheta`, `ϑ`, + `\Iota`, `Ι`, + `\iota`, `ι`, + `\Kappa`, `Κ`, + `\kappa`, `κ`, + `\Lambda`, `Λ`, + `\lambda`, `λ`, + `\Mu`, `Μ`, + `\mu`, `μ`, + `\nu`, `ν`, + `\Nu`, `Ν`, + `\Xi`, `Ξ`, + `\xi`, `ξ`, + `\Omicron`, `Ο`, + `\omicron`, `ο`, + `\Pi`, `Π`, + `\pi`, `π`, + `\Rho`, `Ρ`, + `\rho`, `ρ`, + `\Sigma`, `Σ`, + `\sigma`, `σ`, + `\sigmaf`, `ς`, + `\varsigma`, `ς`, + `\Tau`, `Τ`, + `\Upsilon`, `Υ`, + `\upsih`, `ϒ`, + `\upsilon`, `υ`, + `\Phi`, `Φ`, + `\phi`, `ɸ`, + `\varphi`, `φ`, + `\Chi`, `Χ`, + `\chi`, `χ`, + `\acutex`, `𝑥́`, + `\Psi`, `Ψ`, + `\psi`, `ψ`, + `\tau`, `τ`, + `\Omega`, `Ω`, + `\omega`, `ω`, + `\piv`, `ϖ`, + `\varpi`, `ϖ`, + `\partial`, `∂`, + `\alefsym`, `ℵ`, + `\aleph`, `ℵ`, + `\gimel`, `ℷ`, + `\beth`, `ב`, + `\dalet`, `ד`, + `\ETH`, `Ð`, + `\eth`, `ð`, + `\THORN`, `Þ`, + `\thorn`, `þ`, + `\dots`, `…`, + `\cdots`, `⋯`, + `\hellip`, `…`, + `\middot`, `·`, + `\iexcl`, `¡`, + `\iquest`, `¿`, + `\shy`, ``, + `\ndash`, `–`, + `\mdash`, `—`, + `\quot`, `"`, + `\acute`, `´`, + `\ldquo`, `“`, + `\rdquo`, `”`, + `\bdquo`, `„`, + `\lsquo`, `‘`, + `\rsquo`, `’`, + `\sbquo`, `‚`, + `\laquo`, `«`, + `\raquo`, `»`, + `\lsaquo`, `‹`, + `\rsaquo`, `›`, + `\circ`, `∘`, + `\vert`, `|`, + `\vbar`, `|`, + `\brvbar`, `¦`, + `\S`, `§`, + `\sect`, `§`, + `\amp`, `&`, + `\lt`, `<`, + `\gt`, `>`, + `\tilde`, `~`, + `\slash`, `/`, + `\plus`, `+`, + `\under`, `_`, + `\equal`, `=`, + `\asciicirc`, `^`, + `\dagger`, `†`, + `\dag`, `†`, + `\Dagger`, `‡`, + `\ddag`, `‡`, + `\nbsp`, ` `, + `\ensp`, ` `, + `\emsp`, ` `, + `\thinsp`, ` `, + `\curren`, `¤`, + `\cent`, `¢`, + `\pound`, `£`, + `\yen`, `¥`, + `\euro`, `€`, + `\EUR`, `€`, + `\dollar`, `$`, + `\USD`, `$`, + `\copy`, `©`, + `\reg`, `®`, + `\trade`, `™`, + `\minus`, `−`, + `\pm`, `±`, + `\plusmn`, `±`, + `\times`, `×`, + `\frasl`, `⁄`, + `\colon`, `:`, + `\div`, `÷`, + `\frac12`, `½`, + `\frac14`, `¼`, + `\frac34`, `¾`, + `\permil`, `‰`, + `\sup1`, `¹`, + `\sup2`, `²`, + `\sup3`, `³`, + `\radic`, `√`, + `\sum`, `∑`, + `\prod`, `∏`, + `\micro`, `µ`, + `\macr`, `¯`, + `\deg`, `°`, + `\prime`, `′`, + `\Prime`, `″`, + `\infin`, `∞`, + `\infty`, `∞`, + `\prop`, `∝`, + `\propto`, `∝`, + `\not`, `¬`, + `\neg`, `¬`, + `\land`, `∧`, + `\wedge`, `∧`, + `\lor`, `∨`, + `\vee`, `∨`, + `\cap`, `∩`, + `\cup`, `∪`, + `\smile`, `⌣`, + `\frown`, `⌢`, + `\int`, `∫`, + `\therefore`, `∴`, + `\there4`, `∴`, + `\because`, `∵`, + `\sim`, `∼`, + `\cong`, `≅`, + `\simeq`, `≅`, + `\asymp`, `≈`, + `\approx`, `≈`, + `\ne`, `≠`, + `\neq`, `≠`, + `\equiv`, `≡`, + `\triangleq`, `≜`, + `\le`, `≤`, + `\leq`, `≤`, + `\ge`, `≥`, + `\geq`, `≥`, + `\lessgtr`, `≶`, + `\lesseqgtr`, `⋚`, + `\ll`, `≪`, + `\Ll`, `⋘`, + `\lll`, `⋘`, + `\gg`, `≫`, + `\Gg`, `⋙`, + `\ggg`, `⋙`, + `\prec`, `≺`, + `\preceq`, `≼`, + `\preccurlyeq`, `≼`, + `\succ`, `≻`, + `\succeq`, `≽`, + `\succcurlyeq`, `≽`, + `\sub`, `⊂`, + `\subset`, `⊂`, + `\sup`, `⊃`, + `\supset`, `⊃`, + `\nsub`, `⊄`, + `\sube`, `⊆`, + `\nsup`, `⊅`, + `\supe`, `⊇`, + `\setminus`, `⧵`, + `\forall`, `∀`, + `\exist`, `∃`, + `\exists`, `∃`, + `\nexist`, `∄`, + `\nexists`, `∄`, + `\empty`, `∅`, + `\emptyset`, `∅`, + `\isin`, `∈`, + `\in`, `∈`, + `\notin`, `∉`, + `\ni`, `∋`, + `\nabla`, `∇`, + `\ang`, `∠`, + `\angle`, `∠`, + `\perp`, `⊥`, + `\parallel`, `∥`, + `\sdot`, `⋅`, + `\cdot`, `⋅`, + `\lceil`, `⌈`, + `\rceil`, `⌉`, + `\lfloor`, `⌊`, + `\rfloor`, `⌋`, + `\lang`, `⟨`, + `\rang`, `⟩`, + `\langle`, `⟨`, + `\rangle`, `⟩`, + `\hbar`, `ℏ`, + `\mho`, `℧`, + `\larr`, `←`, + `\leftarrow`, `←`, + `\gets`, `←`, + `\lArr`, `⇐`, + `\Leftarrow`, `⇐`, + `\uarr`, `↑`, + `\uparrow`, `↑`, + `\uArr`, `⇑`, + `\Uparrow`, `⇑`, + `\rarr`, `→`, + `\to`, `→`, + `\rightarrow`, `→`, + `\rArr`, `⇒`, + `\Rightarrow`, `⇒`, + `\darr`, `↓`, + `\downarrow`, `↓`, + `\dArr`, `⇓`, + `\Downarrow`, `⇓`, + `\harr`, `↔`, + `\leftrightarrow`, `↔`, + `\hArr`, `⇔`, + `\Leftrightarrow`, `⇔`, + `\crarr`, `↵`, + `\hookleftarrow`, `↵`, + `\arccos`, `arccos`, + `\arcsin`, `arcsin`, + `\arctan`, `arctan`, + `\arg`, `arg`, + `\cos`, `cos`, + `\cosh`, `cosh`, + `\cot`, `cot`, + `\coth`, `coth`, + `\csc`, `csc`, + `\deg`, `deg`, + `\det`, `det`, + `\dim`, `dim`, + `\exp`, `exp`, + `\gcd`, `gcd`, + `\hom`, `hom`, + `\inf`, `inf`, + `\ker`, `ker`, + `\lg`, `lg`, + `\lim`, `lim`, + `\liminf`, `liminf`, + `\limsup`, `limsup`, + `\ln`, `ln`, + `\log`, `log`, + `\max`, `max`, + `\min`, `min`, + `\Pr`, `Pr`, + `\sec`, `sec`, + `\sin`, `sin`, + `\sinh`, `sinh`, + `\sup`, `sup`, + `\tan`, `tan`, + `\tanh`, `tanh`, + `\bull`, `•`, + `\bullet`, `•`, + `\star`, `⋆`, + `\lowast`, `∗`, + `\ast`, `*`, + `\odot`, `ʘ`, + `\oplus`, `⊕`, + `\otimes`, `⊗`, + `\check`, `✓`, + `\checkmark`, `✓`, + `\para`, `¶`, + `\ordf`, `ª`, + `\ordm`, `º`, + `\cedil`, `¸`, + `\oline`, `‾`, + `\uml`, `¨`, + `\zwnj`, `‌`, + `\zwj`, `‍`, + `\lrm`, `‎`, + `\rlm`, `‏`, + `\smiley`, `☺`, + `\blacksmile`, `☻`, + `\sad`, `☹`, + `\frowny`, `☹`, + `\clubs`, `♣`, + `\clubsuit`, `♣`, + `\spades`, `♠`, + `\spadesuit`, `♠`, + `\hearts`, `♥`, + `\heartsuit`, `♥`, + `\diams`, `◆`, + `\diamondsuit`, `◆`, + `\diamond`, `◆`, + `\Diamond`, `◆`, + `\loz`, `⧫`, + `\_ `, ` `, + `\_ `, `  `, + `\_ `, `   `, + `\_ `, `    `, + `\_ `, `     `, + `\_ `, `      `, + `\_ `, `       `, + `\_ `, `        `, + `\_ `, `         `, + `\_ `, `          `, + `\_ `, `           `, + `\_ `, `            `, + `\_ `, `             `, + `\_ `, `              `, + `\_ `, `               `, + `\_ `, `                `, + `\_ `, `                 `, + `\_ `, `                  `, + `\_ `, `                   `, + `\_ `, `                    `, +} diff --git a/vendor/github.com/niklasfasching/go-org/org/html_writer.go b/vendor/github.com/niklasfasching/go-org/org/html_writer.go new file mode 100644 index 0000000000..90a48c6b4b --- /dev/null +++ b/vendor/github.com/niklasfasching/go-org/org/html_writer.go @@ -0,0 +1,504 @@ +package org + +import ( + "fmt" + "html" + "log" + "regexp" + "strings" + "unicode" + + h "golang.org/x/net/html" + "golang.org/x/net/html/atom" +) + +// HTMLWriter exports an org document into a html document. +type HTMLWriter struct { + ExtendingWriter Writer + HighlightCodeBlock func(source, lang string) string + + strings.Builder + document *Document + htmlEscape bool + log *log.Logger + footnotes *footnotes +} + +type footnotes struct { + mapping map[string]int + list []*FootnoteDefinition +} + +var emphasisTags = map[string][]string{ + "/": []string{"", ""}, + "*": []string{"", ""}, + "+": []string{"", ""}, + "~": []string{"", ""}, + "=": []string{``, ""}, + "_": []string{``, ""}, + "_{}": []string{"", ""}, + "^{}": []string{"", ""}, +} + +var listTags = map[string][]string{ + "unordered": []string{"
    ", "
"}, + "ordered": []string{"
    ", "
"}, + "descriptive": []string{"
", "
"}, +} + +var listItemStatuses = map[string]string{ + " ": "unchecked", + "-": "indeterminate", + "X": "checked", +} + +var cleanHeadlineTitleForHTMLAnchorRegexp = regexp.MustCompile(`]*>`) // nested a tags are not valid HTML + +func NewHTMLWriter() *HTMLWriter { + defaultConfig := New() + return &HTMLWriter{ + document: &Document{Configuration: defaultConfig}, + log: defaultConfig.Log, + htmlEscape: true, + HighlightCodeBlock: func(source, lang string) string { + return fmt.Sprintf("
\n
\n%s\n
\n
", html.EscapeString(source)) + }, + footnotes: &footnotes{ + mapping: map[string]int{}, + }, + } +} + +func (w *HTMLWriter) emptyClone() *HTMLWriter { + wcopy := *w + wcopy.Builder = strings.Builder{} + return &wcopy +} + +func (w *HTMLWriter) nodesAsString(nodes ...Node) string { + tmp := w.emptyClone() + WriteNodes(tmp, nodes...) + return tmp.String() +} + +func (w *HTMLWriter) WriterWithExtensions() Writer { + if w.ExtendingWriter != nil { + return w.ExtendingWriter + } + return w +} + +func (w *HTMLWriter) Before(d *Document) { + w.document = d + w.log = d.Log + w.WriteOutline(d) +} + +func (w *HTMLWriter) After(d *Document) { + w.WriteFootnotes(d) +} + +func (w *HTMLWriter) WriteComment(Comment) {} +func (w *HTMLWriter) WritePropertyDrawer(PropertyDrawer) {} + +func (w *HTMLWriter) WriteBlock(b Block) { + content := "" + if isRawTextBlock(b.Name) { + exportWriter := w.emptyClone() + exportWriter.htmlEscape = false + WriteNodes(exportWriter, b.Children...) + content = strings.TrimRightFunc(exportWriter.String(), unicode.IsSpace) + } else { + content = w.nodesAsString(b.Children...) + } + switch name := b.Name; { + case name == "SRC": + lang := "text" + if len(b.Parameters) >= 1 { + lang = strings.ToLower(b.Parameters[0]) + } + content = w.HighlightCodeBlock(content, lang) + w.WriteString(fmt.Sprintf("
\n%s\n
\n", lang, content)) + case name == "EXAMPLE": + w.WriteString(`
` + "\n" + content + "\n
\n") + case name == "EXPORT" && len(b.Parameters) >= 1 && strings.ToLower(b.Parameters[0]) == "html": + w.WriteString(content + "\n") + case name == "QUOTE": + w.WriteString("
\n" + content + "
\n") + case name == "CENTER": + w.WriteString(`
` + "\n") + w.WriteString(content + "
\n") + default: + w.WriteString(fmt.Sprintf(`
`, strings.ToLower(b.Name)) + "\n") + w.WriteString(content + "
\n") + } +} + +func (w *HTMLWriter) WriteDrawer(d Drawer) { + WriteNodes(w, d.Children...) +} + +func (w *HTMLWriter) WriteKeyword(k Keyword) { + if k.Key == "HTML" { + w.WriteString(k.Value + "\n") + } +} + +func (w *HTMLWriter) WriteInclude(i Include) { + WriteNodes(w, i.Resolve()) +} + +func (w *HTMLWriter) WriteFootnoteDefinition(f FootnoteDefinition) { + w.footnotes.updateDefinition(f) +} + +func (w *HTMLWriter) WriteFootnotes(d *Document) { + if !w.document.GetOption("f") || len(w.footnotes.list) == 0 { + return + } + w.WriteString(`
` + "\n") + w.WriteString(`
` + "\n") + w.WriteString(`
` + "\n") + for i, definition := range w.footnotes.list { + id := i + 1 + if definition == nil { + name := "" + for k, v := range w.footnotes.mapping { + if v == i { + name = k + } + } + w.log.Printf("Missing footnote definition for [fn:%s] (#%d)", name, id) + continue + } + w.WriteString(`
` + "\n") + w.WriteString(fmt.Sprintf(`%d`, id, id, id) + "\n") + w.WriteString(`
` + "\n") + WriteNodes(w, definition.Children...) + w.WriteString("
\n
\n") + } + w.WriteString("
\n
\n") +} + +func (w *HTMLWriter) WriteOutline(d *Document) { + if w.document.GetOption("toc") && len(d.Outline.Children) != 0 { + w.WriteString("\n") + } +} + +func (w *HTMLWriter) writeSection(section *Section) { + // NOTE: To satisfy hugo ExtractTOC() check we cannot use `
  • \n` here. Doesn't really matter, just a note. + w.WriteString("
  • ") + h := section.Headline + title := cleanHeadlineTitleForHTMLAnchorRegexp.ReplaceAllString(w.nodesAsString(h.Title...), "") + w.WriteString(fmt.Sprintf("%s\n", h.ID(), title)) + if len(section.Children) != 0 { + w.WriteString("
      \n") + for _, section := range section.Children { + w.writeSection(section) + } + w.WriteString("
    \n") + } + w.WriteString("
  • \n") +} + +func (w *HTMLWriter) WriteHeadline(h Headline) { + for _, excludeTag := range strings.Fields(w.document.Get("EXCLUDE_TAGS")) { + for _, tag := range h.Tags { + if excludeTag == tag { + return + } + } + } + + w.WriteString(fmt.Sprintf(``, h.Lvl, h.ID()) + "\n") + if w.document.GetOption("todo") && h.Status != "" { + w.WriteString(fmt.Sprintf(`%s`, h.Status) + "\n") + } + if w.document.GetOption("pri") && h.Priority != "" { + w.WriteString(fmt.Sprintf(`[%s]`, h.Priority) + "\n") + } + + WriteNodes(w, h.Title...) + if w.document.GetOption("tags") && len(h.Tags) != 0 { + tags := make([]string, len(h.Tags)) + for i, tag := range h.Tags { + tags[i] = fmt.Sprintf(`%s`, tag) + } + w.WriteString("   ") + w.WriteString(fmt.Sprintf(`%s`, strings.Join(tags, " "))) + } + w.WriteString(fmt.Sprintf("\n\n", h.Lvl)) + WriteNodes(w, h.Children...) +} + +func (w *HTMLWriter) WriteText(t Text) { + if !w.htmlEscape { + w.WriteString(t.Content) + } else if !w.document.GetOption("e") || t.IsRaw { + w.WriteString(html.EscapeString(t.Content)) + } else { + w.WriteString(html.EscapeString(htmlEntityReplacer.Replace(t.Content))) + } +} + +func (w *HTMLWriter) WriteEmphasis(e Emphasis) { + tags, ok := emphasisTags[e.Kind] + if !ok { + panic(fmt.Sprintf("bad emphasis %#v", e)) + } + w.WriteString(tags[0]) + WriteNodes(w, e.Content...) + w.WriteString(tags[1]) +} + +func (w *HTMLWriter) WriteLatexFragment(l LatexFragment) { + w.WriteString(l.OpeningPair) + WriteNodes(w, l.Content...) + w.WriteString(l.ClosingPair) +} + +func (w *HTMLWriter) WriteStatisticToken(s StatisticToken) { + w.WriteString(fmt.Sprintf(`[%s]`, s.Content)) +} + +func (w *HTMLWriter) WriteLineBreak(l LineBreak) { + w.WriteString(strings.Repeat("\n", l.Count)) +} + +func (w *HTMLWriter) WriteExplicitLineBreak(l ExplicitLineBreak) { + w.WriteString("
    \n") +} + +func (w *HTMLWriter) WriteFootnoteLink(l FootnoteLink) { + if !w.document.GetOption("f") { + return + } + i := w.footnotes.add(l) + id := i + 1 + w.WriteString(fmt.Sprintf(`%d`, id, id, id)) +} + +func (w *HTMLWriter) WriteTimestamp(t Timestamp) { + if !w.document.GetOption("<") { + return + } + w.WriteString(`<`) + if t.IsDate { + w.WriteString(t.Time.Format(datestampFormat)) + } else { + w.WriteString(t.Time.Format(timestampFormat)) + } + if t.Interval != "" { + w.WriteString(" " + t.Interval) + } + w.WriteString(`>`) +} + +func (w *HTMLWriter) WriteRegularLink(l RegularLink) { + url := html.EscapeString(l.URL) + if l.Protocol == "file" { + url = url[len("file:"):] + } + description := url + if l.Description != nil { + description = w.nodesAsString(l.Description...) + } + switch l.Kind() { + case "image": + w.WriteString(fmt.Sprintf(`%s`, url, description, description)) + case "video": + w.WriteString(fmt.Sprintf(``, url, description, description)) + default: + w.WriteString(fmt.Sprintf(`%s`, url, description)) + } +} + +func (w *HTMLWriter) WriteList(l List) { + tags, ok := listTags[l.Kind] + if !ok { + panic(fmt.Sprintf("bad list kind %#v", l)) + } + w.WriteString(tags[0] + "\n") + WriteNodes(w, l.Items...) + w.WriteString(tags[1] + "\n") +} + +func (w *HTMLWriter) WriteListItem(li ListItem) { + if li.Status != "" { + w.WriteString(fmt.Sprintf("
  • \n", listItemStatuses[li.Status])) + } else { + w.WriteString("
  • \n") + } + WriteNodes(w, li.Children...) + w.WriteString("
  • \n") +} + +func (w *HTMLWriter) WriteDescriptiveListItem(di DescriptiveListItem) { + if di.Status != "" { + w.WriteString(fmt.Sprintf("
    \n", listItemStatuses[di.Status])) + } else { + w.WriteString("
    \n") + } + + if len(di.Term) != 0 { + WriteNodes(w, di.Term...) + } else { + w.WriteString("?") + } + w.WriteString("\n
    \n") + w.WriteString("
    \n") + WriteNodes(w, di.Details...) + w.WriteString("
    \n") +} + +func (w *HTMLWriter) WriteParagraph(p Paragraph) { + if len(p.Children) == 0 { + return + } + w.WriteString("

    ") + if _, ok := p.Children[0].(LineBreak); !ok { + w.WriteString("\n") + } + WriteNodes(w, p.Children...) + w.WriteString("\n

    \n") +} + +func (w *HTMLWriter) WriteExample(e Example) { + w.WriteString(`
    ` + "\n")
    +	if len(e.Children) != 0 {
    +		for _, n := range e.Children {
    +			WriteNodes(w, n)
    +			w.WriteString("\n")
    +		}
    +	}
    +	w.WriteString("
    \n") +} + +func (w *HTMLWriter) WriteHorizontalRule(h HorizontalRule) { + w.WriteString("
    \n") +} + +func (w *HTMLWriter) WriteNodeWithMeta(n NodeWithMeta) { + out := w.nodesAsString(n.Node) + if p, ok := n.Node.(Paragraph); ok { + if len(p.Children) == 1 && isImageOrVideoLink(p.Children[0]) { + out = w.nodesAsString(p.Children[0]) + } + } + for _, attributes := range n.Meta.HTMLAttributes { + out = w.withHTMLAttributes(out, attributes...) + "\n" + } + if len(n.Meta.Caption) != 0 { + caption := "" + for i, ns := range n.Meta.Caption { + if i != 0 { + caption += " " + } + caption += w.nodesAsString(ns...) + } + out = fmt.Sprintf("
    \n%s
    \n%s\n
    \n
    \n", out, caption) + } + w.WriteString(out) +} + +func (w *HTMLWriter) WriteNodeWithName(n NodeWithName) { + WriteNodes(w, n.Node) +} + +func (w *HTMLWriter) WriteTable(t Table) { + w.WriteString("\n") + beforeFirstContentRow := true + for i, row := range t.Rows { + if row.IsSpecial || len(row.Columns) == 0 { + continue + } + if beforeFirstContentRow { + beforeFirstContentRow = false + if i+1 < len(t.Rows) && len(t.Rows[i+1].Columns) == 0 { + w.WriteString("\n") + w.writeTableColumns(row.Columns, "th") + w.WriteString("\n\n") + continue + } else { + w.WriteString("\n") + } + } + w.writeTableColumns(row.Columns, "td") + } + w.WriteString("\n
    \n") +} + +func (w *HTMLWriter) writeTableColumns(columns []Column, tag string) { + w.WriteString("\n") + for _, column := range columns { + if column.Align == "" { + w.WriteString(fmt.Sprintf("<%s>", tag)) + } else { + w.WriteString(fmt.Sprintf(`<%s class="align-%s">`, tag, column.Align)) + } + WriteNodes(w, column.Children...) + w.WriteString(fmt.Sprintf("\n", tag)) + } + w.WriteString("\n") +} + +func (w *HTMLWriter) withHTMLAttributes(input string, kvs ...string) string { + if len(kvs)%2 != 0 { + w.log.Printf("withHTMLAttributes: Len of kvs must be even: %#v", kvs) + return input + } + context := &h.Node{Type: h.ElementNode, Data: "body", DataAtom: atom.Body} + nodes, err := h.ParseFragment(strings.NewReader(strings.TrimSpace(input)), context) + if err != nil || len(nodes) != 1 { + w.log.Printf("withHTMLAttributes: Could not extend attributes of %s: %v (%s)", input, nodes, err) + return input + } + out, node := strings.Builder{}, nodes[0] + for i := 0; i < len(kvs)-1; i += 2 { + node.Attr = setHTMLAttribute(node.Attr, strings.TrimPrefix(kvs[i], ":"), kvs[i+1]) + } + err = h.Render(&out, nodes[0]) + if err != nil { + w.log.Printf("withHTMLAttributes: Could not extend attributes of %s: %v (%s)", input, node, err) + return input + } + return out.String() +} + +func setHTMLAttribute(attributes []h.Attribute, k, v string) []h.Attribute { + for i, a := range attributes { + if strings.ToLower(a.Key) == strings.ToLower(k) { + switch strings.ToLower(k) { + case "class", "style": + attributes[i].Val += " " + v + default: + attributes[i].Val = v + } + return attributes + } + } + return append(attributes, h.Attribute{Namespace: "", Key: k, Val: v}) +} + +func (fs *footnotes) add(f FootnoteLink) int { + if i, ok := fs.mapping[f.Name]; ok && f.Name != "" { + return i + } + fs.list = append(fs.list, f.Definition) + i := len(fs.list) - 1 + if f.Name != "" { + fs.mapping[f.Name] = i + } + return i +} + +func (fs *footnotes) updateDefinition(f FootnoteDefinition) { + if i, ok := fs.mapping[f.Name]; ok { + fs.list[i] = &f + } +} diff --git a/vendor/github.com/niklasfasching/go-org/org/inline.go b/vendor/github.com/niklasfasching/go-org/org/inline.go new file mode 100644 index 0000000000..02d5a15341 --- /dev/null +++ b/vendor/github.com/niklasfasching/go-org/org/inline.go @@ -0,0 +1,357 @@ +package org + +import ( + "fmt" + "path" + "regexp" + "strings" + "time" + "unicode" +) + +type Text struct { + Content string + IsRaw bool +} + +type LineBreak struct{ Count int } +type ExplicitLineBreak struct{} + +type StatisticToken struct{ Content string } + +type Timestamp struct { + Time time.Time + IsDate bool + Interval string +} + +type Emphasis struct { + Kind string + Content []Node +} + +type LatexFragment struct { + OpeningPair string + ClosingPair string + Content []Node +} + +type FootnoteLink struct { + Name string + Definition *FootnoteDefinition +} + +type RegularLink struct { + Protocol string + Description []Node + URL string + AutoLink bool +} + +var validURLCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=" +var autolinkProtocols = regexp.MustCompile(`^(https?|ftp|file)$`) +var imageExtensionRegexp = regexp.MustCompile(`^[.](png|gif|jpe?g|svg|tiff?)$`) +var videoExtensionRegexp = regexp.MustCompile(`^[.](webm|mp4)$`) + +var subScriptSuperScriptRegexp = regexp.MustCompile(`^([_^]){([^{}]+?)}`) +var timestampRegexp = regexp.MustCompile(`^<(\d{4}-\d{2}-\d{2})( [A-Za-z]+)?( \d{2}:\d{2})?( \+\d+[dwmy])?>`) +var footnoteRegexp = regexp.MustCompile(`^\[fn:([\w-]*?)(:(.*?))?\]`) +var statisticsTokenRegexp = regexp.MustCompile(`^\[(\d+/\d+|\d+%)\]`) +var latexFragmentRegexp = regexp.MustCompile(`(?s)^\\begin{(\w+)}(.*)\\end{(\w+)}`) + +var timestampFormat = "2006-01-02 Mon 15:04" +var datestampFormat = "2006-01-02 Mon" + +var latexFragmentPairs = map[string]string{ + `\(`: `\)`, + `\[`: `\]`, + `$$`: `$$`, +} + +func (d *Document) parseInline(input string) (nodes []Node) { + previous, current := 0, 0 + for current < len(input) { + rewind, consumed, node := 0, 0, (Node)(nil) + switch input[current] { + case '^': + consumed, node = d.parseSubOrSuperScript(input, current) + case '_': + consumed, node = d.parseSubScriptOrEmphasis(input, current) + case '*', '/', '+': + consumed, node = d.parseEmphasis(input, current, false) + case '=', '~': + consumed, node = d.parseEmphasis(input, current, true) + case '[': + consumed, node = d.parseOpeningBracket(input, current) + case '<': + consumed, node = d.parseTimestamp(input, current) + case '\\': + consumed, node = d.parseExplicitLineBreakOrLatexFragment(input, current) + case '$': + consumed, node = d.parseLatexFragment(input, current) + case '\n': + consumed, node = d.parseLineBreak(input, current) + case ':': + rewind, consumed, node = d.parseAutoLink(input, current) + current -= rewind + } + if consumed != 0 { + if current > previous { + nodes = append(nodes, Text{input[previous:current], false}) + } + if node != nil { + nodes = append(nodes, node) + } + current += consumed + previous = current + } else { + current++ + } + } + + if previous < len(input) { + nodes = append(nodes, Text{input[previous:], false}) + } + return nodes +} + +func (d *Document) parseRawInline(input string) (nodes []Node) { + previous, current := 0, 0 + for current < len(input) { + if input[current] == '\n' { + consumed, node := d.parseLineBreak(input, current) + if current > previous { + nodes = append(nodes, Text{input[previous:current], true}) + } + nodes = append(nodes, node) + current += consumed + previous = current + } else { + current++ + } + } + if previous < len(input) { + nodes = append(nodes, Text{input[previous:], true}) + } + return nodes +} + +func (d *Document) parseLineBreak(input string, start int) (int, Node) { + i := start + for ; i < len(input) && input[i] == '\n'; i++ { + } + return i - start, LineBreak{i - start} +} + +func (d *Document) parseExplicitLineBreakOrLatexFragment(input string, start int) (int, Node) { + switch { + case start+2 >= len(input): + case input[start+1] == '\\' && start != 0 && input[start-1] != '\n': + for i := start + 2; unicode.IsSpace(rune(input[i])); i++ { + if i >= len(input) || input[i] == '\n' { + return i + 1 - start, ExplicitLineBreak{} + } + } + case input[start+1] == '(' || input[start+1] == '[': + return d.parseLatexFragment(input, start) + case strings.Index(input[start:], `\begin{`) == 0: + if m := latexFragmentRegexp.FindStringSubmatch(input[start:]); m != nil { + if open, content, close := m[1], m[2], m[3]; open == close { + openingPair, closingPair := `\begin{`+open+`}`, `\end{`+close+`}` + i := strings.Index(input[start:], closingPair) + return i + len(closingPair), LatexFragment{openingPair, closingPair, d.parseRawInline(content)} + } + } + } + return 0, nil +} + +func (d *Document) parseLatexFragment(input string, start int) (int, Node) { + if start+2 >= len(input) { + return 0, nil + } + openingPair := input[start : start+2] + closingPair := latexFragmentPairs[openingPair] + if i := strings.Index(input[start+2:], closingPair); i != -1 { + content := d.parseRawInline(input[start+2 : start+2+i]) + return i + 2 + 2, LatexFragment{openingPair, closingPair, content} + } + return 0, nil +} + +func (d *Document) parseSubOrSuperScript(input string, start int) (int, Node) { + if m := subScriptSuperScriptRegexp.FindStringSubmatch(input[start:]); m != nil { + return len(m[2]) + 3, Emphasis{m[1] + "{}", []Node{Text{m[2], false}}} + } + return 0, nil +} + +func (d *Document) parseSubScriptOrEmphasis(input string, start int) (int, Node) { + if consumed, node := d.parseSubOrSuperScript(input, start); consumed != 0 { + return consumed, node + } + return d.parseEmphasis(input, start, false) +} + +func (d *Document) parseOpeningBracket(input string, start int) (int, Node) { + if len(input[start:]) >= 2 && input[start] == '[' && input[start+1] == '[' { + return d.parseRegularLink(input, start) + } else if footnoteRegexp.MatchString(input[start:]) { + return d.parseFootnoteReference(input, start) + } else if statisticsTokenRegexp.MatchString(input[start:]) { + return d.parseStatisticToken(input, start) + } + return 0, nil +} + +func (d *Document) parseFootnoteReference(input string, start int) (int, Node) { + if m := footnoteRegexp.FindStringSubmatch(input[start:]); m != nil { + name, definition := m[1], m[3] + if name == "" && definition == "" { + return 0, nil + } + link := FootnoteLink{name, nil} + if definition != "" { + link.Definition = &FootnoteDefinition{name, []Node{Paragraph{d.parseInline(definition)}}, true} + } + return len(m[0]), link + } + return 0, nil +} + +func (d *Document) parseStatisticToken(input string, start int) (int, Node) { + if m := statisticsTokenRegexp.FindStringSubmatch(input[start:]); m != nil { + return len(m[1]) + 2, StatisticToken{m[1]} + } + return 0, nil +} + +func (d *Document) parseAutoLink(input string, start int) (int, int, Node) { + if !d.AutoLink || start == 0 || len(input[start:]) < 3 || input[start:start+3] != "://" { + return 0, 0, nil + } + protocolStart, protocol := start-1, "" + for ; protocolStart > 0; protocolStart-- { + if !unicode.IsLetter(rune(input[protocolStart])) { + protocolStart++ + break + } + } + if m := autolinkProtocols.FindStringSubmatch(input[protocolStart:start]); m != nil { + protocol = m[1] + } else { + return 0, 0, nil + } + end := start + for ; end < len(input) && strings.ContainsRune(validURLCharacters, rune(input[end])); end++ { + } + path := input[start:end] + if path == "://" { + return 0, 0, nil + } + return len(protocol), len(path + protocol), RegularLink{protocol, nil, protocol + path, true} +} + +func (d *Document) parseRegularLink(input string, start int) (int, Node) { + input = input[start:] + if len(input) < 3 || input[:2] != "[[" || input[2] == '[' { + return 0, nil + } + end := strings.Index(input, "]]") + if end == -1 { + return 0, nil + } + rawLinkParts := strings.Split(input[2:end], "][") + description, link := ([]Node)(nil), rawLinkParts[0] + if len(rawLinkParts) == 2 { + link, description = rawLinkParts[0], d.parseInline(rawLinkParts[1]) + } + if strings.ContainsRune(link, '\n') { + return 0, nil + } + consumed := end + 2 + protocol, linkParts := "", strings.SplitN(link, ":", 2) + if len(linkParts) == 2 { + protocol = linkParts[0] + } + return consumed, RegularLink{protocol, description, link, false} +} + +func (d *Document) parseTimestamp(input string, start int) (int, Node) { + if m := timestampRegexp.FindStringSubmatch(input[start:]); m != nil { + ddmmyy, hhmm, interval, isDate := m[1], m[3], strings.TrimSpace(m[4]), false + if hhmm == "" { + hhmm, isDate = "00:00", true + } + t, err := time.Parse(timestampFormat, fmt.Sprintf("%s Mon %s", ddmmyy, hhmm)) + if err != nil { + return 0, nil + } + timestamp := Timestamp{t, isDate, interval} + return len(m[0]), timestamp + } + return 0, nil +} + +func (d *Document) parseEmphasis(input string, start int, isRaw bool) (int, Node) { + marker, i := input[start], start + if !hasValidPreAndBorderChars(input, i) { + return 0, nil + } + for i, consumedNewLines := i+1, 0; i < len(input) && consumedNewLines <= d.MaxEmphasisNewLines; i++ { + if input[i] == '\n' { + consumedNewLines++ + } + + if input[i] == marker && i != start+1 && hasValidPostAndBorderChars(input, i) { + if isRaw { + return i + 1 - start, Emphasis{input[start : start+1], d.parseRawInline(input[start+1 : i])} + } + return i + 1 - start, Emphasis{input[start : start+1], d.parseInline(input[start+1 : i])} + } + } + return 0, nil +} + +// see org-emphasis-regexp-components (emacs elisp variable) + +func hasValidPreAndBorderChars(input string, i int) bool { + return (i+1 >= len(input) || isValidBorderChar(rune(input[i+1]))) && (i == 0 || isValidPreChar(rune(input[i-1]))) +} + +func hasValidPostAndBorderChars(input string, i int) bool { + return (i == 0 || isValidBorderChar(rune(input[i-1]))) && (i+1 >= len(input) || isValidPostChar(rune(input[i+1]))) +} + +func isValidPreChar(r rune) bool { + return unicode.IsSpace(r) || strings.ContainsRune(`-({'"`, r) +} + +func isValidPostChar(r rune) bool { + return unicode.IsSpace(r) || strings.ContainsRune(`-.,:!?;'")}[`, r) +} + +func isValidBorderChar(r rune) bool { return !unicode.IsSpace(r) } + +func (l RegularLink) Kind() string { + if p := l.Protocol; l.Description != nil || (p != "" && p != "file" && p != "http" && p != "https") { + return "regular" + } + if imageExtensionRegexp.MatchString(path.Ext(l.URL)) { + return "image" + } + if videoExtensionRegexp.MatchString(path.Ext(l.URL)) { + return "video" + } + return "regular" +} + +func (n Text) String() string { return orgWriter.nodesAsString(n) } +func (n LineBreak) String() string { return orgWriter.nodesAsString(n) } +func (n ExplicitLineBreak) String() string { return orgWriter.nodesAsString(n) } +func (n StatisticToken) String() string { return orgWriter.nodesAsString(n) } +func (n Emphasis) String() string { return orgWriter.nodesAsString(n) } +func (n LatexFragment) String() string { return orgWriter.nodesAsString(n) } +func (n FootnoteLink) String() string { return orgWriter.nodesAsString(n) } +func (n RegularLink) String() string { return orgWriter.nodesAsString(n) } +func (n Timestamp) String() string { return orgWriter.nodesAsString(n) } diff --git a/vendor/github.com/niklasfasching/go-org/org/keyword.go b/vendor/github.com/niklasfasching/go-org/org/keyword.go new file mode 100644 index 0000000000..776241797b --- /dev/null +++ b/vendor/github.com/niklasfasching/go-org/org/keyword.go @@ -0,0 +1,184 @@ +package org + +import ( + "bytes" + "path/filepath" + "regexp" + "strings" +) + +type Comment struct{ Content string } + +type Keyword struct { + Key string + Value string +} + +type NodeWithName struct { + Name string + Node Node +} + +type NodeWithMeta struct { + Node Node + Meta Metadata +} + +type Metadata struct { + Caption [][]Node + HTMLAttributes [][]string +} + +type Include struct { + Keyword + Resolve func() Node +} + +var keywordRegexp = regexp.MustCompile(`^(\s*)#\+([^:]+):(\s+(.*)|$)`) +var commentRegexp = regexp.MustCompile(`^(\s*)#(.*)`) + +var includeFileRegexp = regexp.MustCompile(`(?i)^"([^"]+)" (src|example|export) (\w+)$`) +var attributeRegexp = regexp.MustCompile(`(?:^|\s+)(:[-\w]+)\s+(.*)$`) + +func lexKeywordOrComment(line string) (token, bool) { + if m := keywordRegexp.FindStringSubmatch(line); m != nil { + return token{"keyword", len(m[1]), m[2], m}, true + } else if m := commentRegexp.FindStringSubmatch(line); m != nil { + return token{"comment", len(m[1]), m[2], m}, true + } + return nilToken, false +} + +func (d *Document) parseComment(i int, stop stopFn) (int, Node) { + return 1, Comment{d.tokens[i].content} +} + +func (d *Document) parseKeyword(i int, stop stopFn) (int, Node) { + k := parseKeyword(d.tokens[i]) + switch k.Key { + case "NAME": + return d.parseNodeWithName(k, i, stop) + case "SETUPFILE": + return d.loadSetupFile(k) + case "INCLUDE": + return d.parseInclude(k) + case "CAPTION", "ATTR_HTML": + consumed, node := d.parseAffiliated(i, stop) + if consumed != 0 { + return consumed, node + } + fallthrough + default: + if _, ok := d.BufferSettings[k.Key]; ok { + d.BufferSettings[k.Key] = strings.Join([]string{d.BufferSettings[k.Key], k.Value}, "\n") + } else { + d.BufferSettings[k.Key] = k.Value + } + return 1, k + } +} + +func (d *Document) parseNodeWithName(k Keyword, i int, stop stopFn) (int, Node) { + if stop(d, i+1) { + return 0, nil + } + consumed, node := d.parseOne(i+1, stop) + if consumed == 0 || node == nil { + return 0, nil + } + d.NamedNodes[k.Value] = node + return consumed + 1, NodeWithName{k.Value, node} +} + +func (d *Document) parseAffiliated(i int, stop stopFn) (int, Node) { + start, meta := i, Metadata{} + for ; !stop(d, i) && d.tokens[i].kind == "keyword"; i++ { + switch k := parseKeyword(d.tokens[i]); k.Key { + case "CAPTION": + meta.Caption = append(meta.Caption, d.parseInline(k.Value)) + case "ATTR_HTML": + attributes, rest := []string{}, k.Value + for { + if k, m := "", attributeRegexp.FindStringSubmatch(rest); m != nil { + k, rest = m[1], m[2] + attributes = append(attributes, k) + if v, m := "", attributeRegexp.FindStringSubmatchIndex(rest); m != nil { + v, rest = rest[:m[0]], rest[m[0]:] + attributes = append(attributes, v) + } else { + attributes = append(attributes, strings.TrimSpace(rest)) + break + } + } else { + break + } + } + meta.HTMLAttributes = append(meta.HTMLAttributes, attributes) + default: + return 0, nil + } + } + if stop(d, i) { + return 0, nil + } + consumed, node := d.parseOne(i, stop) + if consumed == 0 || node == nil { + return 0, nil + } + i += consumed + return i - start, NodeWithMeta{node, meta} +} + +func parseKeyword(t token) Keyword { + k, v := t.matches[2], t.matches[4] + return Keyword{strings.ToUpper(k), strings.TrimSpace(v)} +} + +func (d *Document) parseInclude(k Keyword) (int, Node) { + resolve := func() Node { + d.Log.Printf("Bad include %#v", k) + return k + } + if m := includeFileRegexp.FindStringSubmatch(k.Value); m != nil { + path, kind, lang := m[1], m[2], m[3] + if !filepath.IsAbs(path) { + path = filepath.Join(filepath.Dir(d.Path), path) + } + resolve = func() Node { + bs, err := d.ReadFile(path) + if err != nil { + d.Log.Printf("Bad include %#v: %s", k, err) + return k + } + return Block{strings.ToUpper(kind), []string{lang}, d.parseRawInline(string(bs))} + } + } + return 1, Include{k, resolve} +} + +func (d *Document) loadSetupFile(k Keyword) (int, Node) { + path := k.Value + if !filepath.IsAbs(path) { + path = filepath.Join(filepath.Dir(d.Path), path) + } + bs, err := d.ReadFile(path) + if err != nil { + d.Log.Printf("Bad setup file: %#v: %s", k, err) + return 1, k + } + setupDocument := d.Configuration.Parse(bytes.NewReader(bs), path) + if err := setupDocument.Error; err != nil { + d.Log.Printf("Bad setup file: %#v: %s", k, err) + return 1, k + } + for k, v := range setupDocument.BufferSettings { + d.BufferSettings[k] = v + } + return 1, k +} + +func (n Comment) String() string { return orgWriter.nodesAsString(n) } +func (n Keyword) String() string { return orgWriter.nodesAsString(n) } +func (n NodeWithMeta) String() string { return orgWriter.nodesAsString(n) } +func (n NodeWithName) String() string { return orgWriter.nodesAsString(n) } +func (n Include) String() string { return orgWriter.nodesAsString(n) } diff --git a/vendor/github.com/niklasfasching/go-org/org/list.go b/vendor/github.com/niklasfasching/go-org/org/list.go new file mode 100644 index 0000000000..6ba28f6fe4 --- /dev/null +++ b/vendor/github.com/niklasfasching/go-org/org/list.go @@ -0,0 +1,114 @@ +package org + +import ( + "fmt" + "regexp" + "strings" + "unicode" +) + +type List struct { + Kind string + Items []Node +} + +type ListItem struct { + Bullet string + Status string + Children []Node +} + +type DescriptiveListItem struct { + Bullet string + Status string + Term []Node + Details []Node +} + +var unorderedListRegexp = regexp.MustCompile(`^(\s*)([+*-])(\s+(.*)|$)`) +var orderedListRegexp = regexp.MustCompile(`^(\s*)(([0-9]+|[a-zA-Z])[.)])(\s+(.*)|$)`) +var descriptiveListItemRegexp = regexp.MustCompile(`\s::(\s|$)`) +var listItemStatusRegexp = regexp.MustCompile(`\[( |X|-)\]\s`) + +func lexList(line string) (token, bool) { + if m := unorderedListRegexp.FindStringSubmatch(line); m != nil { + return token{"unorderedList", len(m[1]), m[4], m}, true + } else if m := orderedListRegexp.FindStringSubmatch(line); m != nil { + return token{"orderedList", len(m[1]), m[5], m}, true + } + return nilToken, false +} + +func isListToken(t token) bool { + return t.kind == "unorderedList" || t.kind == "orderedList" +} + +func listKind(t token) (string, string) { + kind := "" + switch bullet := t.matches[2]; { + case bullet == "*" || bullet == "+" || bullet == "-": + kind = "unordered" + case unicode.IsLetter(rune(bullet[0])), unicode.IsDigit(rune(bullet[0])): + kind = "ordered" + default: + panic(fmt.Sprintf("bad list bullet '%s': %#v", bullet, t)) + } + if descriptiveListItemRegexp.MatchString(t.content) { + return kind, "descriptive" + } + return kind, kind +} + +func (d *Document) parseList(i int, parentStop stopFn) (int, Node) { + start, lvl := i, d.tokens[i].lvl + listMainKind, kind := listKind(d.tokens[i]) + list := List{Kind: kind} + stop := func(*Document, int) bool { + if parentStop(d, i) || d.tokens[i].lvl != lvl || !isListToken(d.tokens[i]) { + return true + } + itemMainKind, _ := listKind(d.tokens[i]) + return itemMainKind != listMainKind + } + for !stop(d, i) { + consumed, node := d.parseListItem(list, i, parentStop) + i += consumed + list.Items = append(list.Items, node) + } + return i - start, list +} + +func (d *Document) parseListItem(l List, i int, parentStop stopFn) (int, Node) { + start, nodes, bullet := i, []Node{}, d.tokens[i].matches[2] + minIndent, dterm, content, status := d.tokens[i].lvl+len(bullet), "", d.tokens[i].content, "" + if m := listItemStatusRegexp.FindStringSubmatch(content); m != nil { + status, content = m[1], content[len("[ ] "):] + } + if l.Kind == "descriptive" { + if m := descriptiveListItemRegexp.FindStringIndex(content); m != nil { + dterm, content = content[:m[0]], content[m[1]:] + } + } + + d.tokens[i] = tokenize(strings.Repeat(" ", minIndent) + content) + stop := func(d *Document, i int) bool { + if parentStop(d, i) { + return true + } + t := d.tokens[i] + return t.lvl < minIndent && !(t.kind == "text" && t.content == "") + } + for !stop(d, i) && (i <= start+1 || !isSecondBlankLine(d, i)) { + consumed, node := d.parseOne(i, stop) + i += consumed + nodes = append(nodes, node) + } + if l.Kind == "descriptive" { + return i - start, DescriptiveListItem{bullet, status, d.parseInline(dterm), nodes} + } + return i - start, ListItem{bullet, status, nodes} +} + +func (n List) String() string { return orgWriter.nodesAsString(n) } +func (n ListItem) String() string { return orgWriter.nodesAsString(n) } +func (n DescriptiveListItem) String() string { return orgWriter.nodesAsString(n) } diff --git a/vendor/github.com/niklasfasching/go-org/org/org_writer.go b/vendor/github.com/niklasfasching/go-org/org/org_writer.go new file mode 100644 index 0000000000..d574cda527 --- /dev/null +++ b/vendor/github.com/niklasfasching/go-org/org/org_writer.go @@ -0,0 +1,334 @@ +package org + +import ( + "fmt" + "strings" + "unicode" + "unicode/utf8" +) + +// OrgWriter export an org document into pretty printed org document. +type OrgWriter struct { + ExtendingWriter Writer + TagsColumn int + + strings.Builder + indent string +} + +var emphasisOrgBorders = map[string][]string{ + "_": []string{"_", "_"}, + "*": []string{"*", "*"}, + "/": []string{"/", "/"}, + "+": []string{"+", "+"}, + "~": []string{"~", "~"}, + "=": []string{"=", "="}, + "_{}": []string{"_{", "}"}, + "^{}": []string{"^{", "}"}, +} + +func NewOrgWriter() *OrgWriter { + return &OrgWriter{ + TagsColumn: 77, + } +} + +func (w *OrgWriter) WriterWithExtensions() Writer { + if w.ExtendingWriter != nil { + return w.ExtendingWriter + } + return w +} + +func (w *OrgWriter) Before(d *Document) {} +func (w *OrgWriter) After(d *Document) {} + +func (w *OrgWriter) emptyClone() *OrgWriter { + wcopy := *w + wcopy.Builder = strings.Builder{} + return &wcopy +} + +func (w *OrgWriter) nodesAsString(nodes ...Node) string { + tmp := w.emptyClone() + WriteNodes(tmp, nodes...) + return tmp.String() +} + +func (w *OrgWriter) WriteHeadline(h Headline) { + tmp := w.emptyClone() + tmp.WriteString(strings.Repeat("*", h.Lvl)) + if h.Status != "" { + tmp.WriteString(" " + h.Status) + } + if h.Priority != "" { + tmp.WriteString(" [#" + h.Priority + "]") + } + tmp.WriteString(" ") + WriteNodes(tmp, h.Title...) + hString := tmp.String() + if len(h.Tags) != 0 { + tString := ":" + strings.Join(h.Tags, ":") + ":" + if n := w.TagsColumn - len(tString) - len(hString); n > 0 { + w.WriteString(hString + strings.Repeat(" ", n) + tString) + } else { + w.WriteString(hString + " " + tString) + } + } else { + w.WriteString(hString) + } + w.WriteString("\n") + if len(h.Children) != 0 { + w.WriteString(w.indent) + } + if h.Properties != nil { + WriteNodes(w, *h.Properties) + } + WriteNodes(w, h.Children...) +} + +func (w *OrgWriter) WriteBlock(b Block) { + w.WriteString(w.indent + "#+BEGIN_" + b.Name) + if len(b.Parameters) != 0 { + w.WriteString(" " + strings.Join(b.Parameters, " ")) + } + w.WriteString("\n") + if isRawTextBlock(b.Name) { + w.WriteString(w.indent) + } + WriteNodes(w, b.Children...) + if !isRawTextBlock(b.Name) { + w.WriteString(w.indent) + } + w.WriteString("#+END_" + b.Name + "\n") +} + +func (w *OrgWriter) WriteDrawer(d Drawer) { + w.WriteString(w.indent + ":" + d.Name + ":\n") + WriteNodes(w, d.Children...) + w.WriteString(w.indent + ":END:\n") +} + +func (w *OrgWriter) WritePropertyDrawer(d PropertyDrawer) { + w.WriteString(":PROPERTIES:\n") + for _, kvPair := range d.Properties { + k, v := kvPair[0], kvPair[1] + if v != "" { + v = " " + v + } + w.WriteString(fmt.Sprintf(":%s:%s\n", k, v)) + } + w.WriteString(":END:\n") +} + +func (w *OrgWriter) WriteFootnoteDefinition(f FootnoteDefinition) { + w.WriteString(fmt.Sprintf("[fn:%s]", f.Name)) + content := w.nodesAsString(f.Children...) + if content != "" && !unicode.IsSpace(rune(content[0])) { + w.WriteString(" ") + } + w.WriteString(content) +} + +func (w *OrgWriter) WriteParagraph(p Paragraph) { + content := w.nodesAsString(p.Children...) + if len(content) > 0 && content[0] != '\n' { + w.WriteString(w.indent) + } + w.WriteString(content + "\n") +} + +func (w *OrgWriter) WriteExample(e Example) { + for _, n := range e.Children { + w.WriteString(w.indent + ":") + if content := w.nodesAsString(n); content != "" { + w.WriteString(" " + content) + } + w.WriteString("\n") + } +} + +func (w *OrgWriter) WriteKeyword(k Keyword) { + w.WriteString(w.indent + "#+" + k.Key + ":") + if k.Value != "" { + w.WriteString(" " + k.Value) + } + w.WriteString("\n") +} + +func (w *OrgWriter) WriteInclude(i Include) { + w.WriteKeyword(i.Keyword) +} + +func (w *OrgWriter) WriteNodeWithMeta(n NodeWithMeta) { + for _, ns := range n.Meta.Caption { + w.WriteString("#+CAPTION: ") + WriteNodes(w, ns...) + w.WriteString("\n") + } + for _, attributes := range n.Meta.HTMLAttributes { + w.WriteString("#+ATTR_HTML: ") + w.WriteString(strings.Join(attributes, " ") + "\n") + } + WriteNodes(w, n.Node) +} + +func (w *OrgWriter) WriteNodeWithName(n NodeWithName) { + w.WriteString(fmt.Sprintf("#+NAME: %s\n", n.Name)) + WriteNodes(w, n.Node) +} + +func (w *OrgWriter) WriteComment(c Comment) { + w.WriteString(w.indent + "#" + c.Content + "\n") +} + +func (w *OrgWriter) WriteList(l List) { WriteNodes(w, l.Items...) } + +func (w *OrgWriter) WriteListItem(li ListItem) { + liWriter := w.emptyClone() + liWriter.indent = w.indent + strings.Repeat(" ", len(li.Bullet)+1) + WriteNodes(liWriter, li.Children...) + content := strings.TrimPrefix(liWriter.String(), liWriter.indent) + w.WriteString(w.indent + li.Bullet) + if li.Status != "" { + w.WriteString(fmt.Sprintf(" [%s]", li.Status)) + } + if len(content) > 0 && content[0] == '\n' { + w.WriteString(content) + } else { + w.WriteString(" " + content) + } +} + +func (w *OrgWriter) WriteDescriptiveListItem(di DescriptiveListItem) { + w.WriteString(w.indent + di.Bullet) + if di.Status != "" { + w.WriteString(fmt.Sprintf(" [%s]", di.Status)) + } + indent := w.indent + strings.Repeat(" ", len(di.Bullet)+1) + if len(di.Term) != 0 { + term := w.nodesAsString(di.Term...) + w.WriteString(" " + term + " ::") + indent = indent + strings.Repeat(" ", len(term)+4) + } + diWriter := w.emptyClone() + diWriter.indent = indent + WriteNodes(diWriter, di.Details...) + details := strings.TrimPrefix(diWriter.String(), diWriter.indent) + if len(details) > 0 && details[0] == '\n' { + w.WriteString(details) + } else { + w.WriteString(" " + details) + } +} + +func (w *OrgWriter) WriteTable(t Table) { + for _, row := range t.Rows { + w.WriteString(w.indent) + if len(row.Columns) == 0 { + w.WriteString(`|`) + for i := 0; i < len(t.ColumnInfos); i++ { + w.WriteString(strings.Repeat("-", t.ColumnInfos[i].Len+2)) + if i < len(t.ColumnInfos)-1 { + w.WriteString("+") + } + } + w.WriteString(`|`) + + } else { + w.WriteString(`|`) + for _, column := range row.Columns { + w.WriteString(` `) + content := w.nodesAsString(column.Children...) + if content == "" { + content = " " + } + n := column.Len - utf8.RuneCountInString(content) + if n < 0 { + n = 0 + } + if column.Align == "center" { + if n%2 != 0 { + w.WriteString(" ") + } + w.WriteString(strings.Repeat(" ", n/2) + content + strings.Repeat(" ", n/2)) + } else if column.Align == "right" { + w.WriteString(strings.Repeat(" ", n) + content) + } else { + w.WriteString(content + strings.Repeat(" ", n)) + } + w.WriteString(` |`) + } + } + w.WriteString("\n") + } +} + +func (w *OrgWriter) WriteHorizontalRule(hr HorizontalRule) { + w.WriteString(w.indent + "-----\n") +} + +func (w *OrgWriter) WriteText(t Text) { w.WriteString(t.Content) } + +func (w *OrgWriter) WriteEmphasis(e Emphasis) { + borders, ok := emphasisOrgBorders[e.Kind] + if !ok { + panic(fmt.Sprintf("bad emphasis %#v", e)) + } + w.WriteString(borders[0]) + WriteNodes(w, e.Content...) + w.WriteString(borders[1]) +} + +func (w *OrgWriter) WriteLatexFragment(l LatexFragment) { + w.WriteString(l.OpeningPair) + WriteNodes(w, l.Content...) + w.WriteString(l.ClosingPair) +} + +func (w *OrgWriter) WriteStatisticToken(s StatisticToken) { + w.WriteString(fmt.Sprintf("[%s]", s.Content)) +} + +func (w *OrgWriter) WriteLineBreak(l LineBreak) { + w.WriteString(strings.Repeat("\n"+w.indent, l.Count)) +} + +func (w *OrgWriter) WriteExplicitLineBreak(l ExplicitLineBreak) { + w.WriteString(`\\` + "\n" + w.indent) +} + +func (w *OrgWriter) WriteTimestamp(t Timestamp) { + w.WriteString("<") + if t.IsDate { + w.WriteString(t.Time.Format(datestampFormat)) + } else { + w.WriteString(t.Time.Format(timestampFormat)) + } + if t.Interval != "" { + w.WriteString(" " + t.Interval) + } + w.WriteString(">") +} + +func (w *OrgWriter) WriteFootnoteLink(l FootnoteLink) { + w.WriteString("[fn:" + l.Name) + if l.Definition != nil { + w.WriteString(":") + WriteNodes(w, l.Definition.Children[0].(Paragraph).Children...) + } + w.WriteString("]") +} + +func (w *OrgWriter) WriteRegularLink(l RegularLink) { + if l.AutoLink { + w.WriteString(l.URL) + } else if l.Description == nil { + w.WriteString(fmt.Sprintf("[[%s]]", l.URL)) + } else { + descriptionWriter := w.emptyClone() + WriteNodes(descriptionWriter, l.Description...) + description := descriptionWriter.String() + w.WriteString(fmt.Sprintf("[[%s][%s]]", l.URL, description)) + } +} diff --git a/vendor/github.com/niklasfasching/go-org/org/paragraph.go b/vendor/github.com/niklasfasching/go-org/org/paragraph.go new file mode 100644 index 0000000000..b7d3ea92ce --- /dev/null +++ b/vendor/github.com/niklasfasching/go-org/org/paragraph.go @@ -0,0 +1,46 @@ +package org + +import ( + "regexp" + "strings" +) + +type Paragraph struct{ Children []Node } +type HorizontalRule struct{} + +var horizontalRuleRegexp = regexp.MustCompile(`^(\s*)-{5,}\s*$`) +var plainTextRegexp = regexp.MustCompile(`^(\s*)(.*)`) + +func lexText(line string) (token, bool) { + if m := plainTextRegexp.FindStringSubmatch(line); m != nil { + return token{"text", len(m[1]), m[2], m}, true + } + return nilToken, false +} + +func lexHorizontalRule(line string) (token, bool) { + if m := horizontalRuleRegexp.FindStringSubmatch(line); m != nil { + return token{"horizontalRule", len(m[1]), "", m}, true + } + return nilToken, false +} + +func (d *Document) parseParagraph(i int, parentStop stopFn) (int, Node) { + lines, start := []string{d.tokens[i].content}, i + i++ + stop := func(d *Document, i int) bool { + return parentStop(d, i) || d.tokens[i].kind != "text" || d.tokens[i].content == "" + } + for ; !stop(d, i); i++ { + lines = append(lines, d.tokens[i].content) + } + consumed := i - start + return consumed, Paragraph{d.parseInline(strings.Join(lines, "\n"))} +} + +func (d *Document) parseHorizontalRule(i int, parentStop stopFn) (int, Node) { + return 1, HorizontalRule{} +} + +func (n Paragraph) String() string { return orgWriter.nodesAsString(n) } +func (n HorizontalRule) String() string { return orgWriter.nodesAsString(n) } diff --git a/vendor/github.com/niklasfasching/go-org/org/table.go b/vendor/github.com/niklasfasching/go-org/org/table.go new file mode 100644 index 0000000000..a404e1a9f2 --- /dev/null +++ b/vendor/github.com/niklasfasching/go-org/org/table.go @@ -0,0 +1,130 @@ +package org + +import ( + "regexp" + "strconv" + "strings" + "unicode/utf8" +) + +type Table struct { + Rows []Row + ColumnInfos []ColumnInfo +} + +type Row struct { + Columns []Column + IsSpecial bool +} + +type Column struct { + Children []Node + *ColumnInfo +} + +type ColumnInfo struct { + Align string + Len int +} + +var tableSeparatorRegexp = regexp.MustCompile(`^(\s*)(\|[+-|]*)\s*$`) +var tableRowRegexp = regexp.MustCompile(`^(\s*)(\|.*)`) + +var columnAlignRegexp = regexp.MustCompile(`^<(l|c|r)>$`) + +func lexTable(line string) (token, bool) { + if m := tableSeparatorRegexp.FindStringSubmatch(line); m != nil { + return token{"tableSeparator", len(m[1]), m[2], m}, true + } else if m := tableRowRegexp.FindStringSubmatch(line); m != nil { + return token{"tableRow", len(m[1]), m[2], m}, true + } + return nilToken, false +} + +func (d *Document) parseTable(i int, parentStop stopFn) (int, Node) { + rawRows, start := [][]string{}, i + for ; !parentStop(d, i); i++ { + if t := d.tokens[i]; t.kind == "tableRow" { + rawRow := strings.FieldsFunc(d.tokens[i].content, func(r rune) bool { return r == '|' }) + for i := range rawRow { + rawRow[i] = strings.TrimSpace(rawRow[i]) + } + rawRows = append(rawRows, rawRow) + } else if t.kind == "tableSeparator" { + rawRows = append(rawRows, nil) + } else { + break + } + } + + table := Table{nil, getColumnInfos(rawRows)} + for _, rawColumns := range rawRows { + row := Row{nil, isSpecialRow(rawColumns)} + if len(rawColumns) != 0 { + for i := range table.ColumnInfos { + column := Column{nil, &table.ColumnInfos[i]} + if i < len(rawColumns) { + column.Children = d.parseInline(rawColumns[i]) + } + row.Columns = append(row.Columns, column) + } + } + table.Rows = append(table.Rows, row) + } + return i - start, table +} + +func getColumnInfos(rows [][]string) []ColumnInfo { + columnCount := 0 + for _, columns := range rows { + if n := len(columns); n > columnCount { + columnCount = n + } + } + + columnInfos := make([]ColumnInfo, columnCount) + for i := 0; i < columnCount; i++ { + countNumeric, countNonNumeric := 0, 0 + for _, columns := range rows { + if i >= len(columns) { + continue + } + + if n := utf8.RuneCountInString(columns[i]); n > columnInfos[i].Len { + columnInfos[i].Len = n + } + + if m := columnAlignRegexp.FindStringSubmatch(columns[i]); m != nil && isSpecialRow(columns) { + switch m[1] { + case "l": + columnInfos[i].Align = "left" + case "c": + columnInfos[i].Align = "center" + case "r": + columnInfos[i].Align = "right" + } + } else if _, err := strconv.ParseFloat(columns[i], 32); err == nil { + countNumeric++ + } else if strings.TrimSpace(columns[i]) != "" { + countNonNumeric++ + } + } + + if columnInfos[i].Align == "" && countNumeric >= countNonNumeric { + columnInfos[i].Align = "right" + } + } + return columnInfos +} + +func isSpecialRow(rawColumns []string) bool { + isAlignRow := true + for _, rawColumn := range rawColumns { + if !columnAlignRegexp.MatchString(rawColumn) && rawColumn != "" { + isAlignRow = false + } + } + return isAlignRow +} + +func (n Table) String() string { return orgWriter.nodesAsString(n) } diff --git a/vendor/github.com/niklasfasching/go-org/org/util.go b/vendor/github.com/niklasfasching/go-org/org/util.go new file mode 100644 index 0000000000..c25bf27ee2 --- /dev/null +++ b/vendor/github.com/niklasfasching/go-org/org/util.go @@ -0,0 +1,19 @@ +package org + +func isSecondBlankLine(d *Document, i int) bool { + if i-1 <= 0 { + return false + } + t1, t2 := d.tokens[i-1], d.tokens[i] + if t1.kind == "text" && t2.kind == "text" && t1.content == "" && t2.content == "" { + return true + } + return false +} + +func isImageOrVideoLink(n Node) bool { + if l, ok := n.(RegularLink); ok && l.Kind() == "video" || l.Kind() == "image" { + return true + } + return false +} diff --git a/vendor/github.com/niklasfasching/go-org/org/writer.go b/vendor/github.com/niklasfasching/go-org/org/writer.go new file mode 100644 index 0000000000..c4aebd69f5 --- /dev/null +++ b/vendor/github.com/niklasfasching/go-org/org/writer.go @@ -0,0 +1,103 @@ +package org + +import "fmt" + +// Writer is the interface that is used to export a parsed document into a new format. See Document.Write(). +type Writer interface { + Before(*Document) // Before is called before any nodes are passed to the writer. + After(*Document) // After is called after all nodes have been passed to the writer. + String() string // String is called at the very end to retrieve the final output. + + WriterWithExtensions() Writer + + WriteKeyword(Keyword) + WriteInclude(Include) + WriteComment(Comment) + WriteNodeWithMeta(NodeWithMeta) + WriteNodeWithName(NodeWithName) + WriteHeadline(Headline) + WriteBlock(Block) + WriteExample(Example) + WriteDrawer(Drawer) + WritePropertyDrawer(PropertyDrawer) + WriteList(List) + WriteListItem(ListItem) + WriteDescriptiveListItem(DescriptiveListItem) + WriteTable(Table) + WriteHorizontalRule(HorizontalRule) + WriteParagraph(Paragraph) + WriteText(Text) + WriteEmphasis(Emphasis) + WriteLatexFragment(LatexFragment) + WriteStatisticToken(StatisticToken) + WriteExplicitLineBreak(ExplicitLineBreak) + WriteLineBreak(LineBreak) + WriteRegularLink(RegularLink) + WriteTimestamp(Timestamp) + WriteFootnoteLink(FootnoteLink) + WriteFootnoteDefinition(FootnoteDefinition) +} + +func WriteNodes(w Writer, nodes ...Node) { + w = w.WriterWithExtensions() + for _, n := range nodes { + switch n := n.(type) { + case Keyword: + w.WriteKeyword(n) + case Include: + w.WriteInclude(n) + case Comment: + w.WriteComment(n) + case NodeWithMeta: + w.WriteNodeWithMeta(n) + case NodeWithName: + w.WriteNodeWithName(n) + case Headline: + w.WriteHeadline(n) + case Block: + w.WriteBlock(n) + case Example: + w.WriteExample(n) + case Drawer: + w.WriteDrawer(n) + case PropertyDrawer: + w.WritePropertyDrawer(n) + case List: + w.WriteList(n) + case ListItem: + w.WriteListItem(n) + case DescriptiveListItem: + w.WriteDescriptiveListItem(n) + case Table: + w.WriteTable(n) + case HorizontalRule: + w.WriteHorizontalRule(n) + case Paragraph: + w.WriteParagraph(n) + case Text: + w.WriteText(n) + case Emphasis: + w.WriteEmphasis(n) + case LatexFragment: + w.WriteLatexFragment(n) + case StatisticToken: + w.WriteStatisticToken(n) + case ExplicitLineBreak: + w.WriteExplicitLineBreak(n) + case LineBreak: + w.WriteLineBreak(n) + case RegularLink: + w.WriteRegularLink(n) + case Timestamp: + w.WriteTimestamp(n) + case FootnoteLink: + w.WriteFootnoteLink(n) + case FootnoteDefinition: + w.WriteFootnoteDefinition(n) + default: + if n != nil { + panic(fmt.Sprintf("bad node %T %#v", n, n)) + } + } + } +} diff --git a/vendor/github.com/russross/blackfriday/doc.go b/vendor/github.com/russross/blackfriday/doc.go deleted file mode 100644 index 9656c42a19..0000000000 --- a/vendor/github.com/russross/blackfriday/doc.go +++ /dev/null @@ -1,32 +0,0 @@ -// Package blackfriday is a Markdown processor. -// -// It translates plain text with simple formatting rules into HTML or LaTeX. -// -// Sanitized Anchor Names -// -// Blackfriday includes an algorithm for creating sanitized anchor names -// corresponding to a given input text. This algorithm is used to create -// anchors for headings when EXTENSION_AUTO_HEADER_IDS is enabled. The -// algorithm is specified below, so that other packages can create -// compatible anchor names and links to those anchors. -// -// The algorithm iterates over the input text, interpreted as UTF-8, -// one Unicode code point (rune) at a time. All runes that are letters (category L) -// or numbers (category N) are considered valid characters. They are mapped to -// lower case, and included in the output. All other runes are considered -// invalid characters. Invalid characters that preceed the first valid character, -// as well as invalid character that follow the last valid character -// are dropped completely. All other sequences of invalid characters -// between two valid characters are replaced with a single dash character '-'. -// -// SanitizedAnchorName exposes this functionality, and can be used to -// create compatible links to the anchor names generated by blackfriday. -// This algorithm is also implemented in a small standalone package at -// github.com/shurcooL/sanitized_anchor_name. It can be useful for clients -// that want a small package and don't need full functionality of blackfriday. -package blackfriday - -// NOTE: Keep Sanitized Anchor Name algorithm in sync with package -// github.com/shurcooL/sanitized_anchor_name. -// Otherwise, users of sanitized_anchor_name will get anchor names -// that are incompatible with those generated by blackfriday. diff --git a/vendor/github.com/russross/blackfriday/html.go b/vendor/github.com/russross/blackfriday/html.go deleted file mode 100644 index e0a6c69c96..0000000000 --- a/vendor/github.com/russross/blackfriday/html.go +++ /dev/null @@ -1,938 +0,0 @@ -// -// Blackfriday Markdown Processor -// Available at http://github.com/russross/blackfriday -// -// Copyright © 2011 Russ Ross . -// Distributed under the Simplified BSD License. -// See README.md for details. -// - -// -// -// HTML rendering backend -// -// - -package blackfriday - -import ( - "bytes" - "fmt" - "regexp" - "strconv" - "strings" -) - -// Html renderer configuration options. -const ( - HTML_SKIP_HTML = 1 << iota // skip preformatted HTML blocks - HTML_SKIP_STYLE // skip embedded