summaryrefslogtreecommitdiff
path: root/app/views/projects/blob
diff options
context:
space:
mode:
Diffstat (limited to 'app/views/projects/blob')
-rw-r--r--app/views/projects/blob/_auxiliary_viewer.html.haml5
-rw-r--r--app/views/projects/blob/_blob.html.haml29
-rw-r--r--app/views/projects/blob/_breadcrumb.html.haml36
-rw-r--r--app/views/projects/blob/_content.html.haml8
-rw-r--r--app/views/projects/blob/_download.html.haml7
-rw-r--r--app/views/projects/blob/_editor.html.haml20
-rw-r--r--app/views/projects/blob/_header.html.haml40
-rw-r--r--app/views/projects/blob/_header_content.html.haml10
-rw-r--r--app/views/projects/blob/_image.html.haml15
-rw-r--r--app/views/projects/blob/_render_error.html.haml7
-rw-r--r--app/views/projects/blob/_template_selectors.html.haml17
-rw-r--r--app/views/projects/blob/_text.html.haml19
-rw-r--r--app/views/projects/blob/_viewer.html.haml13
-rw-r--r--app/views/projects/blob/_viewer_switcher.html.haml12
-rw-r--r--app/views/projects/blob/edit.html.haml9
-rw-r--r--app/views/projects/blob/new.html.haml8
-rw-r--r--app/views/projects/blob/preview.html.haml10
-rw-r--r--app/views/projects/blob/show.html.haml5
-rw-r--r--app/views/projects/blob/viewers/_balsamiq.html.haml4
-rw-r--r--app/views/projects/blob/viewers/_changelog.html.haml4
-rw-r--r--app/views/projects/blob/viewers/_contributing.html.haml9
-rw-r--r--app/views/projects/blob/viewers/_dependency_manager.html.haml11
-rw-r--r--app/views/projects/blob/viewers/_download.html.haml7
-rw-r--r--app/views/projects/blob/viewers/_empty.html.haml3
-rw-r--r--app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml9
-rw-r--r--app/views/projects/blob/viewers/_gitlab_ci_yml_loading.html.haml4
-rw-r--r--app/views/projects/blob/viewers/_image.html.haml2
-rw-r--r--app/views/projects/blob/viewers/_license.html.haml8
-rw-r--r--app/views/projects/blob/viewers/_loading.html.haml2
-rw-r--r--app/views/projects/blob/viewers/_loading_auxiliary.html.haml2
-rw-r--r--app/views/projects/blob/viewers/_markup.html.haml4
-rw-r--r--app/views/projects/blob/viewers/_notebook.html.haml (renamed from app/views/projects/blob/_notebook.html.haml)2
-rw-r--r--app/views/projects/blob/viewers/_pdf.html.haml5
-rw-r--r--app/views/projects/blob/viewers/_readme.html.haml4
-rw-r--r--app/views/projects/blob/viewers/_route_map.html.haml9
-rw-r--r--app/views/projects/blob/viewers/_route_map_loading.html.haml4
-rw-r--r--app/views/projects/blob/viewers/_sketch.html.haml7
-rw-r--r--app/views/projects/blob/viewers/_stl.html.haml12
-rw-r--r--app/views/projects/blob/viewers/_svg.html.haml4
-rw-r--r--app/views/projects/blob/viewers/_text.html.haml1
-rw-r--r--app/views/projects/blob/viewers/_video.html.haml2
41 files changed, 267 insertions, 122 deletions
diff --git a/app/views/projects/blob/_auxiliary_viewer.html.haml b/app/views/projects/blob/_auxiliary_viewer.html.haml
new file mode 100644
index 00000000000..9749afdc580
--- /dev/null
+++ b/app/views/projects/blob/_auxiliary_viewer.html.haml
@@ -0,0 +1,5 @@
+- blob = local_assigns.fetch(:blob)
+- auxiliary_viewer = blob.auxiliary_viewer
+- if auxiliary_viewer && auxiliary_viewer.render_error.nil? && auxiliary_viewer.visible_to?(current_user)
+ .well-segment.blob-auxiliary-viewer
+ = render 'projects/blob/viewer', viewer: auxiliary_viewer
diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml
index 2b2ee6ed987..8bd336269ff 100644
--- a/app/views/projects/blob/_blob.html.haml
+++ b/app/views/projects/blob/_blob.html.haml
@@ -1,28 +1,13 @@
-.nav-block
- .tree-ref-holder
- = render 'shared/ref_switcher', destination: 'blob', path: @path
+= render "projects/blob/breadcrumb", blob: blob
- %ul.breadcrumb.repo-breadcrumb
- %li
- = link_to namespace_project_tree_path(@project.namespace, @project, @ref) do
- = @project.path
- - tree_breadcrumbs(@tree, 6) do |title, path|
- %li
- - if path
- - if path.end_with?(@path)
- = link_to namespace_project_blob_path(@project.namespace, @project, path) do
- %strong
- = truncate(title, length: 40)
- - else
- = link_to truncate(title, length: 40), namespace_project_tree_path(@project.namespace, @project, path)
- - else
- = link_to title, '#'
+.info-well.hidden-xs
+ .well-segment
+ %ul.blob-commit-info
+ = render 'projects/commits/commit', commit: @last_commit, project: @project, ref: @ref
-%ul.blob-commit-info.hidden-xs
- - blob_commit = @repository.last_commit_for_path(@commit.id, blob.path)
- = render blob_commit, project: @project, ref: @ref
+ = render "projects/blob/auxiliary_viewer", blob: blob
#blob-content-holder.blob-content-holder
%article.file-holder
= render "projects/blob/header", blob: blob
- = render blob.to_partial_path(@project), blob: blob
+ = render 'projects/blob/content', blob: blob
diff --git a/app/views/projects/blob/_breadcrumb.html.haml b/app/views/projects/blob/_breadcrumb.html.haml
new file mode 100644
index 00000000000..3f58e8d232f
--- /dev/null
+++ b/app/views/projects/blob/_breadcrumb.html.haml
@@ -0,0 +1,36 @@
+- blame = local_assigns.fetch(:blame, false)
+.nav-block
+ .tree-controls
+ = render 'projects/find_file_link'
+
+ .btn-group.prepend-left-10{ role: "group" }<
+ -# only show normal/blame view links for text files
+ - if blob.readable_text?
+ - if blame
+ = link_to 'Normal view', namespace_project_blob_path(@project.namespace, @project, @id),
+ class: 'btn'
+ - else
+ = link_to 'Blame', namespace_project_blame_path(@project.namespace, @project, @id),
+ class: 'btn js-blob-blame-link' unless blob.empty?
+
+ = link_to 'History', namespace_project_commits_path(@project.namespace, @project, @id),
+ class: 'btn'
+
+ = link_to 'Permalink', namespace_project_blob_path(@project.namespace, @project,
+ tree_join(@commit.sha, @path)), class: 'btn js-data-file-blob-permalink-url'
+
+ .tree-ref-holder
+ = render 'shared/ref_switcher', destination: 'blob', path: @path
+
+ %ul.breadcrumb.repo-breadcrumb
+ %li
+ = link_to namespace_project_tree_path(@project.namespace, @project, @ref) do
+ = @project.path
+ - path_breadcrumbs do |title, path|
+ - title = truncate(title, length: 40)
+ %li
+ - if path == @path
+ = link_to namespace_project_blob_path(@project.namespace, @project, tree_join(@ref, path)) do
+ %strong= title
+ - else
+ = link_to title, namespace_project_tree_path(@project.namespace, @project, tree_join(@ref, path))
diff --git a/app/views/projects/blob/_content.html.haml b/app/views/projects/blob/_content.html.haml
new file mode 100644
index 00000000000..7afbd85cd6d
--- /dev/null
+++ b/app/views/projects/blob/_content.html.haml
@@ -0,0 +1,8 @@
+- simple_viewer = blob.simple_viewer
+- rich_viewer = blob.rich_viewer
+- rich_viewer_active = rich_viewer && params[:viewer] != 'simple'
+
+= render 'projects/blob/viewer', viewer: simple_viewer, hidden: rich_viewer_active
+
+- if rich_viewer
+ = render 'projects/blob/viewer', viewer: rich_viewer, hidden: !rich_viewer_active
diff --git a/app/views/projects/blob/_download.html.haml b/app/views/projects/blob/_download.html.haml
deleted file mode 100644
index 7908fcae3de..00000000000
--- a/app/views/projects/blob/_download.html.haml
+++ /dev/null
@@ -1,7 +0,0 @@
-.file-content.blob_file.blob-no-preview
- .center
- = link_to namespace_project_raw_path(@project.namespace, @project, @id) do
- %h1.light
- %i.fa.fa-download
- %h4
- Download (#{number_to_human_size blob_size(blob)})
diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml
index e7adef5558a..4b344b2edb9 100644
--- a/app/views/projects/blob/_editor.html.haml
+++ b/app/views/projects/blob/_editor.html.haml
@@ -1,29 +1,23 @@
+- action = current_action?(:edit) || current_action?(:update) ? 'edit' : 'create'
+
.file-holder.file.append-bottom-default
- .js-file-title.file-title.clearfix
+ .js-file-title.file-title.clearfix{ data: { current_action: action } }
.editor-ref
= icon('code-fork')
= ref
%span.editor-file-name
- if current_action?(:edit) || current_action?(:update)
= text_field_tag 'file_path', (params[:file_path] || @path),
- class: 'form-control new-file-path'
+ class: 'form-control new-file-path js-file-path-name-input'
- if current_action?(:new) || current_action?(:create)
%span.editor-file-name
\/
= text_field_tag 'file_name', params[:file_name], placeholder: "File name",
- required: true, class: 'form-control new-file-name'
+ required: true, class: 'form-control new-file-name js-file-path-name-input'
.pull-right.file-buttons
- .license-selector.js-license-selector-wrap.hidden
- = dropdown_tag("Choose a License template", options: { toggle_class: 'btn js-license-selector', title: "Choose a license", filter: true, placeholder: "Filter", data: { data: licenses_for_select, project: @project.name, fullname: @project.namespace.human_name } } )
- .gitignore-selector.js-gitignore-selector-wrap.hidden
- = dropdown_tag("Choose a .gitignore template", options: { toggle_class: 'btn js-gitignore-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { data: gitignore_names } } )
- .gitlab-ci-yml-selector.js-gitlab-ci-yml-selector-wrap.hidden
- = dropdown_tag("Choose a GitLab CI Yaml template", options: { toggle_class: 'btn js-gitlab-ci-yml-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { data: gitlab_ci_ymls } } )
- .dockerfile-selector.js-dockerfile-selector-wrap.hidden
- = dropdown_tag("Choose a Dockerfile template", options: { toggle_class: 'btn js-dockerfile-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { data: dockerfile_names } } )
- = button_tag class: 'soft-wrap-toggle btn', type: 'button' do
+ = button_tag class: 'soft-wrap-toggle btn', type: 'button', tabindex: '-1' do
%span.no-wrap
= custom_icon('icon_no_wrap')
No wrap
@@ -31,7 +25,7 @@
= custom_icon('icon_soft_wrap')
Soft wrap
.encoding-selector
- = select_tag :encoding, options_for_select([ "base64", "text" ], "text"), class: 'select2'
+ = select_tag :encoding, options_for_select([ "base64", "text" ], "text"), class: 'select2', tabindex: '-1'
.file-editor.code
%pre.js-edit-mode-pane#editor= params[:content] || local_assigns[:blob_data]
diff --git a/app/views/projects/blob/_header.html.haml b/app/views/projects/blob/_header.html.haml
index deeeae3d64a..0be15cc179f 100644
--- a/app/views/projects/blob/_header.html.haml
+++ b/app/views/projects/blob/_header.html.haml
@@ -1,39 +1,19 @@
+- blame = local_assigns.fetch(:blame, false)
.js-file-title.file-title-flex-parent
- .file-header-content
- = blob_icon blob.mode, blob.name
-
- %strong.file-title-name
- = blob.name
-
- = copy_file_path_button(blob.path)
-
- %small
- = number_to_human_size(blob_size(blob))
+ = render 'projects/blob/header_content', blob: blob
.file-actions.hidden-xs
+ = render 'projects/blob/viewer_switcher', blob: blob unless blame
+
.btn-group{ role: "group" }<
- = copy_blob_content_button(blob) if blob_text_viewable?(blob)
- = open_raw_file_button(namespace_project_raw_path(@project.namespace, @project, @id))
+ = copy_blob_source_button(blob) unless blame
+ = open_raw_blob_button(blob)
= view_on_environment_button(@commit.sha, @path, @environment) if @environment
.btn-group{ role: "group" }<
- -# only show normal/blame view links for text files
- - if blob_text_viewable?(blob)
- - if current_page? namespace_project_blame_path(@project.namespace, @project, @id)
- = link_to 'Normal View', namespace_project_blob_path(@project.namespace, @project, @id),
- class: 'btn btn-sm'
- - else
- = link_to 'Blame', namespace_project_blame_path(@project.namespace, @project, @id),
- class: 'btn btn-sm js-blob-blame-link' unless blob.empty?
-
- = link_to 'History', namespace_project_commits_path(@project.namespace, @project, @id),
- class: 'btn btn-sm'
-
- = link_to 'Permalink', namespace_project_blob_path(@project.namespace, @project,
- tree_join(@commit.sha, @path)), class: 'btn btn-sm js-data-file-blob-permalink-url'
-
- - if current_user
- .btn-group{ role: "group" }<
- = edit_blob_link if blob_text_viewable?(blob)
+ = edit_blob_link
+ - if current_user
= replace_blob_link
= delete_blob_link
+
+= render 'projects/fork_suggestion'
diff --git a/app/views/projects/blob/_header_content.html.haml b/app/views/projects/blob/_header_content.html.haml
new file mode 100644
index 00000000000..98bedae650a
--- /dev/null
+++ b/app/views/projects/blob/_header_content.html.haml
@@ -0,0 +1,10 @@
+.file-header-content
+ = blob_icon blob.mode, blob.name
+
+ %strong.file-title-name
+ = blob.name
+
+ = copy_file_path_button(blob.path)
+
+ %small
+ = number_to_human_size(blob.raw_size)
diff --git a/app/views/projects/blob/_image.html.haml b/app/views/projects/blob/_image.html.haml
deleted file mode 100644
index ea3cecb86a9..00000000000
--- a/app/views/projects/blob/_image.html.haml
+++ /dev/null
@@ -1,15 +0,0 @@
-.file-content.image_file
- - if blob.svg?
- - if blob.size_within_svg_limits?
- -# We need to scrub SVG but we cannot do so in the RawController: it would
- -# be wrong/strange if RawController modified the data.
- - blob.load_all_data!(@repository)
- - blob = sanitize_svg(blob)
- %img{ src: "data:#{blob.mime_type};base64,#{Base64.encode64(blob.data)}", alt: "#{blob.name}" }
- - else
- .nothing-here-block
- The SVG could not be displayed as it is too large, you can
- #{link_to('view the raw file', namespace_project_raw_path(@project.namespace, @project, @id), target: '_blank', rel: 'noopener noreferrer')}
- instead.
- - else
- %img{ src: namespace_project_raw_path(@project.namespace, @project, tree_join(@commit.id, blob.path)), alt: "#{blob.name}" }
diff --git a/app/views/projects/blob/_render_error.html.haml b/app/views/projects/blob/_render_error.html.haml
new file mode 100644
index 00000000000..9eef6cafd04
--- /dev/null
+++ b/app/views/projects/blob/_render_error.html.haml
@@ -0,0 +1,7 @@
+.file-content.code
+ .nothing-here-block
+ The #{viewer.switcher_title} could not be displayed because #{blob_render_error_reason(viewer)}.
+
+ You can
+ = blob_render_error_options(viewer).to_sentence(two_words_connector: ' or ', last_word_connector: ', or ').html_safe
+ instead.
diff --git a/app/views/projects/blob/_template_selectors.html.haml b/app/views/projects/blob/_template_selectors.html.haml
new file mode 100644
index 00000000000..2a178325041
--- /dev/null
+++ b/app/views/projects/blob/_template_selectors.html.haml
@@ -0,0 +1,17 @@
+.template-selectors-menu
+ .templates-selectors-label
+ Template
+ .template-selector-dropdowns-wrap
+ .template-type-selector.js-template-type-selector-wrap.hidden
+ = dropdown_tag("Choose type", options: { toggle_class: 'btn js-template-type-selector', title: "Choose a template type" } )
+ .license-selector.js-license-selector-wrap.js-template-selector-wrap.hidden
+ = dropdown_tag("Apply a license template", options: { toggle_class: 'btn js-license-selector', title: "Apply a license", filter: true, placeholder: "Filter", data: { data: licenses_for_select, project: @project.name, fullname: @project.namespace.human_name } } )
+ .gitignore-selector.js-gitignore-selector-wrap.js-template-selector-wrap.hidden
+ = dropdown_tag("Apply a .gitignore template", options: { toggle_class: 'btn js-gitignore-selector', title: "Apply a template", filter: true, placeholder: "Filter", data: { data: gitignore_names } } )
+ .gitlab-ci-yml-selector.js-gitlab-ci-yml-selector-wrap.js-template-selector-wrap.hidden
+ = dropdown_tag("Apply a GitLab CI Yaml template", options: { toggle_class: 'btn js-gitlab-ci-yml-selector', title: "Apply a template", filter: true, placeholder: "Filter", data: { data: gitlab_ci_ymls } } )
+ .dockerfile-selector.js-dockerfile-selector-wrap.js-template-selector-wrap.hidden
+ = dropdown_tag("Apply a Dockerfile template", options: { toggle_class: 'btn js-dockerfile-selector', title: "Apply a template", filter: true, placeholder: "Filter", data: { data: dockerfile_names } } )
+ .template-selectors-undo-menu.hidden
+ %span.text-info Template applied
+ %button.btn.btn-sm.btn-info Undo
diff --git a/app/views/projects/blob/_text.html.haml b/app/views/projects/blob/_text.html.haml
deleted file mode 100644
index 7b16d266982..00000000000
--- a/app/views/projects/blob/_text.html.haml
+++ /dev/null
@@ -1,19 +0,0 @@
-- if blob.only_display_raw?
- .file-content.code
- .nothing-here-block
- File too large, you can
- = succeed '.' do
- = link_to 'view the raw file', namespace_project_raw_path(@project.namespace, @project, @id), target: '_blank', rel: 'noopener noreferrer'
-
-- else
- - blob.load_all_data!(@repository)
-
- - if blob.empty?
- .file-content.code
- .nothing-here-block Empty file
- - else
- - if markup?(blob.name)
- .file-content.wiki
- = render_markup(blob.name, blob.data)
- - else
- = render 'shared/file_highlight', blob: blob, repository: @repository
diff --git a/app/views/projects/blob/_viewer.html.haml b/app/views/projects/blob/_viewer.html.haml
new file mode 100644
index 00000000000..4252f27d007
--- /dev/null
+++ b/app/views/projects/blob/_viewer.html.haml
@@ -0,0 +1,13 @@
+- hidden = local_assigns.fetch(:hidden, false)
+- render_error = viewer.render_error
+- load_async = local_assigns.fetch(:load_async, viewer.load_async?)
+
+- viewer_url = local_assigns.fetch(:viewer_url) { url_for(params.merge(viewer: viewer.type, format: :json)) } if load_async
+.blob-viewer{ data: { type: viewer.type, url: viewer_url }, class: ('hidden' if hidden) }
+ - if load_async
+ = render viewer.loading_partial_path, viewer: viewer
+ - elsif render_error
+ = render 'projects/blob/render_error', viewer: viewer
+ - else
+ - viewer.prepare!
+ = render viewer.partial_path, viewer: viewer
diff --git a/app/views/projects/blob/_viewer_switcher.html.haml b/app/views/projects/blob/_viewer_switcher.html.haml
new file mode 100644
index 00000000000..6a521069418
--- /dev/null
+++ b/app/views/projects/blob/_viewer_switcher.html.haml
@@ -0,0 +1,12 @@
+- if blob.show_viewer_switcher?
+ - simple_viewer = blob.simple_viewer
+ - rich_viewer = blob.rich_viewer
+
+ .btn-group.js-blob-viewer-switcher{ role: "group" }
+ - simple_label = "Display #{simple_viewer.switcher_title}"
+ %button.btn.btn-default.btn-sm.js-blob-viewer-switch-btn.has-tooltip{ 'aria-label' => simple_label, title: simple_label, data: { viewer: 'simple', container: 'body' } }>
+ = icon(simple_viewer.switcher_icon)
+
+ - rich_label = "Display #{rich_viewer.switcher_title}"
+ %button.btn.btn-default.btn-sm.js-blob-viewer-switch-btn.has-tooltip{ 'aria-label' => rich_label, title: rich_label, data: { viewer: 'rich', container: 'body' } }>
+ = icon(rich_viewer.switcher_icon)
diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml
index afe0b5dba45..4af62461151 100644
--- a/app/views/projects/blob/edit.html.haml
+++ b/app/views/projects/blob/edit.html.haml
@@ -9,14 +9,17 @@
- if @conflict
.alert.alert-danger
Someone edited the file the same time you did. Please check out
- = link_to "the file", namespace_project_blob_path(@project.namespace, @project, tree_join(@target_branch, @file_path)), target: "_blank", rel: 'noopener noreferrer'
+ = link_to "the file", namespace_project_blob_path(@project.namespace, @project, tree_join(@branch_name, @file_path)), target: "_blank", rel: 'noopener noreferrer'
and make sure your changes will not unintentionally remove theirs.
-
+ .editor-title-row
+ %h3.page-title.blob-edit-page-title
+ Edit file
+ = render 'template_selectors'
.file-editor
%ul.nav-links.no-bottom.js-edit-mode
%li.active
= link_to '#editor' do
- Edit File
+ Write
%li
= link_to '#preview', 'data-preview-url' => namespace_project_preview_blob_path(@project.namespace, @project, @id) do
diff --git a/app/views/projects/blob/new.html.haml b/app/views/projects/blob/new.html.haml
index 4c449e040ee..2afb909572a 100644
--- a/app/views/projects/blob/new.html.haml
+++ b/app/views/projects/blob/new.html.haml
@@ -2,10 +2,10 @@
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('lib/ace.js')
= page_specific_javascript_bundle_tag('blob')
-
-%h3.page-title
- New File
-
+.editor-title-row
+ %h3.page-title.blob-new-page-title
+ New file
+ = render 'template_selectors'
.file-editor
= form_tag(namespace_project_create_blob_path(@project.namespace, @project, @id), method: :post, class: 'form-horizontal js-edit-blob-form js-new-blob-form js-quick-submit js-requires-input', data: blob_editor_paths) do
= render 'projects/blob/editor', ref: @ref
diff --git a/app/views/projects/blob/preview.html.haml b/app/views/projects/blob/preview.html.haml
index 5cafb644b40..da2cef17e8a 100644
--- a/app/views/projects/blob/preview.html.haml
+++ b/app/views/projects/blob/preview.html.haml
@@ -1,12 +1,8 @@
-.diff-file
+.diff-file.file-holder
.diff-content
- - if gitlab_markdown?(@blob.name)
+ - if markup?(@blob.name)
.file-content.wiki
- = preserve do
- = markdown(@content)
- - elsif markup?(@blob.name)
- .file-content.wiki
- = raw render_markup(@blob.name, @content)
+ = markup(@blob.name, @content)
- else
.file-content.code.js-syntax-highlight
- unless @diff_lines.empty?
diff --git a/app/views/projects/blob/show.html.haml b/app/views/projects/blob/show.html.haml
index b6738c3380f..67f57b5e4b9 100644
--- a/app/views/projects/blob/show.html.haml
+++ b/app/views/projects/blob/show.html.haml
@@ -2,13 +2,16 @@
- page_title @blob.path, @ref
= render "projects/commits/head"
+- content_for :page_specific_javascripts do
+ = page_specific_javascript_bundle_tag('blob')
+
%div{ class: container_class }
= render 'projects/last_push'
#tree-holder.tree-holder
= render 'blob', blob: @blob
- - if can_edit_blob?(@blob)
+ - if can_modify_blob?(@blob)
= render 'projects/blob/remove'
- title = "Replace #{@blob.name}"
diff --git a/app/views/projects/blob/viewers/_balsamiq.html.haml b/app/views/projects/blob/viewers/_balsamiq.html.haml
new file mode 100644
index 00000000000..28670e7de97
--- /dev/null
+++ b/app/views/projects/blob/viewers/_balsamiq.html.haml
@@ -0,0 +1,4 @@
+- content_for :page_specific_javascripts do
+ = page_specific_javascript_bundle_tag('balsamiq_viewer')
+
+.file-content.balsamiq-viewer#js-balsamiq-viewer{ data: { endpoint: blob_raw_url } }
diff --git a/app/views/projects/blob/viewers/_changelog.html.haml b/app/views/projects/blob/viewers/_changelog.html.haml
new file mode 100644
index 00000000000..53921e63b5f
--- /dev/null
+++ b/app/views/projects/blob/viewers/_changelog.html.haml
@@ -0,0 +1,4 @@
+= icon('history fw')
+= succeed '.' do
+ To find the state of this project's repository at the time of any of these versions, check out
+ = link_to "the tags", namespace_project_tags_path(viewer.project.namespace, viewer.project)
diff --git a/app/views/projects/blob/viewers/_contributing.html.haml b/app/views/projects/blob/viewers/_contributing.html.haml
new file mode 100644
index 00000000000..c78f04c9c7c
--- /dev/null
+++ b/app/views/projects/blob/viewers/_contributing.html.haml
@@ -0,0 +1,9 @@
+= icon('book fw')
+After you've reviewed these contribution guidelines, you'll be all set to
+
+- options = contribution_options(viewer.project)
+- if options.any?
+ = succeed '.' do
+ = options.to_sentence(two_words_connector: ' or ', last_word_connector: ', or ').html_safe
+- else
+ contribute to this project.
diff --git a/app/views/projects/blob/viewers/_dependency_manager.html.haml b/app/views/projects/blob/viewers/_dependency_manager.html.haml
new file mode 100644
index 00000000000..a0f0215a5ff
--- /dev/null
+++ b/app/views/projects/blob/viewers/_dependency_manager.html.haml
@@ -0,0 +1,11 @@
+= icon('cubes fw')
+= succeed '.' do
+ This project manages its dependencies using
+ %strong= viewer.manager_name
+
+ - if viewer.package_name
+ and defines a #{viewer.package_type} named
+ %strong<
+ = link_to viewer.package_name, viewer.package_url, target: '_blank', rel: 'noopener noreferrer'
+
+= link_to 'Learn more', viewer.manager_url, target: '_blank', rel: 'noopener noreferrer'
diff --git a/app/views/projects/blob/viewers/_download.html.haml b/app/views/projects/blob/viewers/_download.html.haml
new file mode 100644
index 00000000000..684240d02c7
--- /dev/null
+++ b/app/views/projects/blob/viewers/_download.html.haml
@@ -0,0 +1,7 @@
+.file-content.blob_file.blob-no-preview
+ .center
+ = link_to blob_raw_url do
+ %h1.light
+ = icon('download')
+ %h4
+ Download (#{number_to_human_size(viewer.blob.raw_size)})
diff --git a/app/views/projects/blob/viewers/_empty.html.haml b/app/views/projects/blob/viewers/_empty.html.haml
new file mode 100644
index 00000000000..a293a8de231
--- /dev/null
+++ b/app/views/projects/blob/viewers/_empty.html.haml
@@ -0,0 +1,3 @@
+.file-content.code
+ .nothing-here-block
+ Empty file
diff --git a/app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml b/app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml
new file mode 100644
index 00000000000..28c5be6ebf3
--- /dev/null
+++ b/app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml
@@ -0,0 +1,9 @@
+- if viewer.valid?
+ = icon('check fw')
+ This GitLab CI configuration is valid.
+- else
+ = icon('warning fw')
+ This GitLab CI configuration is invalid:
+ = viewer.validation_message
+
+= link_to 'Learn more', help_page_path('ci/yaml/README')
diff --git a/app/views/projects/blob/viewers/_gitlab_ci_yml_loading.html.haml b/app/views/projects/blob/viewers/_gitlab_ci_yml_loading.html.haml
new file mode 100644
index 00000000000..10cbf6a2f7a
--- /dev/null
+++ b/app/views/projects/blob/viewers/_gitlab_ci_yml_loading.html.haml
@@ -0,0 +1,4 @@
+= icon('spinner spin fw')
+Validating GitLab CI configuration…
+
+= link_to 'Learn more', help_page_path('ci/yaml/README')
diff --git a/app/views/projects/blob/viewers/_image.html.haml b/app/views/projects/blob/viewers/_image.html.haml
new file mode 100644
index 00000000000..640d59b3174
--- /dev/null
+++ b/app/views/projects/blob/viewers/_image.html.haml
@@ -0,0 +1,2 @@
+.file-content.image_file
+ %img{ src: blob_raw_url, alt: viewer.blob.name }
diff --git a/app/views/projects/blob/viewers/_license.html.haml b/app/views/projects/blob/viewers/_license.html.haml
new file mode 100644
index 00000000000..fb9d0b99d09
--- /dev/null
+++ b/app/views/projects/blob/viewers/_license.html.haml
@@ -0,0 +1,8 @@
+- license = viewer.license
+
+= icon('balance-scale fw')
+This project is licensed under the
+= succeed '.' do
+ %strong= license.name
+
+= link_to 'Learn more', license.url, target: '_blank', rel: 'noopener noreferrer'
diff --git a/app/views/projects/blob/viewers/_loading.html.haml b/app/views/projects/blob/viewers/_loading.html.haml
new file mode 100644
index 00000000000..120c0540335
--- /dev/null
+++ b/app/views/projects/blob/viewers/_loading.html.haml
@@ -0,0 +1,2 @@
+.text-center.prepend-top-default.append-bottom-default
+ = icon('spinner spin 2x', 'aria-hidden' => 'true', 'aria-label' => 'Loading content…')
diff --git a/app/views/projects/blob/viewers/_loading_auxiliary.html.haml b/app/views/projects/blob/viewers/_loading_auxiliary.html.haml
new file mode 100644
index 00000000000..c7dc9e3250a
--- /dev/null
+++ b/app/views/projects/blob/viewers/_loading_auxiliary.html.haml
@@ -0,0 +1,2 @@
+= icon('spinner spin fw')
+Analyzing file…
diff --git a/app/views/projects/blob/viewers/_markup.html.haml b/app/views/projects/blob/viewers/_markup.html.haml
new file mode 100644
index 00000000000..230305b488d
--- /dev/null
+++ b/app/views/projects/blob/viewers/_markup.html.haml
@@ -0,0 +1,4 @@
+- blob = viewer.blob
+- rendered_markup = blob.rendered_markup if blob.respond_to?(:rendered_markup)
+.file-content.wiki
+ = markup(blob.name, blob.data, rendered: rendered_markup)
diff --git a/app/views/projects/blob/_notebook.html.haml b/app/views/projects/blob/viewers/_notebook.html.haml
index ab1cf933944..2399fb16265 100644
--- a/app/views/projects/blob/_notebook.html.haml
+++ b/app/views/projects/blob/viewers/_notebook.html.haml
@@ -2,4 +2,4 @@
= page_specific_javascript_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('notebook_viewer')
-.file-content#js-notebook-viewer{ data: { endpoint: namespace_project_raw_path(@project.namespace, @project, @id) } }
+.file-content#js-notebook-viewer{ data: { endpoint: blob_raw_url } }
diff --git a/app/views/projects/blob/viewers/_pdf.html.haml b/app/views/projects/blob/viewers/_pdf.html.haml
new file mode 100644
index 00000000000..1dd179c4fdc
--- /dev/null
+++ b/app/views/projects/blob/viewers/_pdf.html.haml
@@ -0,0 +1,5 @@
+- content_for :page_specific_javascripts do
+ = page_specific_javascript_bundle_tag('common_vue')
+ = page_specific_javascript_bundle_tag('pdf_viewer')
+
+.file-content#js-pdf-viewer{ data: { endpoint: blob_raw_url } }
diff --git a/app/views/projects/blob/viewers/_readme.html.haml b/app/views/projects/blob/viewers/_readme.html.haml
new file mode 100644
index 00000000000..334b33faf48
--- /dev/null
+++ b/app/views/projects/blob/viewers/_readme.html.haml
@@ -0,0 +1,4 @@
+= icon('info-circle fw')
+= succeed '.' do
+ To learn more about this project, read
+ = link_to "the wiki", namespace_project_wikis_path(viewer.project.namespace, viewer.project)
diff --git a/app/views/projects/blob/viewers/_route_map.html.haml b/app/views/projects/blob/viewers/_route_map.html.haml
new file mode 100644
index 00000000000..d0fcd55f6c1
--- /dev/null
+++ b/app/views/projects/blob/viewers/_route_map.html.haml
@@ -0,0 +1,9 @@
+- if viewer.valid?
+ = icon('check fw')
+ This Route Map is valid.
+- else
+ = icon('warning fw')
+ This Route Map is invalid:
+ = viewer.validation_message
+
+= link_to 'Learn more', help_page_path('ci/environments', anchor: 'route-map')
diff --git a/app/views/projects/blob/viewers/_route_map_loading.html.haml b/app/views/projects/blob/viewers/_route_map_loading.html.haml
new file mode 100644
index 00000000000..2318cf82f58
--- /dev/null
+++ b/app/views/projects/blob/viewers/_route_map_loading.html.haml
@@ -0,0 +1,4 @@
+= icon('spinner spin fw')
+Validating Route Map…
+
+= link_to 'Learn more', help_page_path('ci/environments', anchor: 'route-map')
diff --git a/app/views/projects/blob/viewers/_sketch.html.haml b/app/views/projects/blob/viewers/_sketch.html.haml
new file mode 100644
index 00000000000..49f716c2c59
--- /dev/null
+++ b/app/views/projects/blob/viewers/_sketch.html.haml
@@ -0,0 +1,7 @@
+- content_for :page_specific_javascripts do
+ = page_specific_javascript_bundle_tag('common_vue')
+ = page_specific_javascript_bundle_tag('sketch_viewer')
+
+.file-content#js-sketch-viewer{ data: { endpoint: blob_raw_url } }
+ .js-loading-icon.text-center.prepend-top-default.append-bottom-default.js-loading-icon{ 'aria-label' => 'Loading Sketch preview' }
+ = icon('spinner spin 2x', 'aria-hidden' => 'true');
diff --git a/app/views/projects/blob/viewers/_stl.html.haml b/app/views/projects/blob/viewers/_stl.html.haml
new file mode 100644
index 00000000000..e4e9d746176
--- /dev/null
+++ b/app/views/projects/blob/viewers/_stl.html.haml
@@ -0,0 +1,12 @@
+- content_for :page_specific_javascripts do
+ = page_specific_javascript_bundle_tag('stl_viewer')
+
+.file-content.is-stl-loading
+ .text-center#js-stl-viewer{ data: { endpoint: blob_raw_url } }
+ = icon('spinner spin 2x', class: 'prepend-top-default append-bottom-default', 'aria-hidden' => 'true', 'aria-label' => 'Loading')
+ .text-center.prepend-top-default.append-bottom-default.stl-controls
+ .btn-group
+ %button.btn.btn-default.btn-sm.js-material-changer{ data: { type: 'wireframe' } }
+ Wireframe
+ %button.btn.btn-default.btn-sm.active.js-material-changer{ data: { type: 'default' } }
+ Solid
diff --git a/app/views/projects/blob/viewers/_svg.html.haml b/app/views/projects/blob/viewers/_svg.html.haml
new file mode 100644
index 00000000000..62f647581b6
--- /dev/null
+++ b/app/views/projects/blob/viewers/_svg.html.haml
@@ -0,0 +1,4 @@
+- blob = viewer.blob
+- data = sanitize_svg_data(blob.data)
+.file-content.image_file
+ %img{ src: "data:#{blob.mime_type};base64,#{Base64.encode64(data)}", alt: blob.name }
diff --git a/app/views/projects/blob/viewers/_text.html.haml b/app/views/projects/blob/viewers/_text.html.haml
new file mode 100644
index 00000000000..a91df321ca0
--- /dev/null
+++ b/app/views/projects/blob/viewers/_text.html.haml
@@ -0,0 +1 @@
+= render 'shared/file_highlight', blob: viewer.blob, repository: @repository
diff --git a/app/views/projects/blob/viewers/_video.html.haml b/app/views/projects/blob/viewers/_video.html.haml
new file mode 100644
index 00000000000..595a890a27d
--- /dev/null
+++ b/app/views/projects/blob/viewers/_video.html.haml
@@ -0,0 +1,2 @@
+.file-content.video
+ %video{ src: blob_raw_url, controls: true, data: { setup: '{}' } }