##// END OF EJS Templates
files: updated based on new design
marcink -
r3706:9aa2b595 new-ui
parent child Browse files
Show More
@@ -1,1393 +1,1392 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2019 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import itertools
21 import itertools
22 import logging
22 import logging
23 import os
23 import os
24 import shutil
24 import shutil
25 import tempfile
25 import tempfile
26 import collections
26 import collections
27 import urllib
27 import urllib
28
28
29 from pyramid.httpexceptions import HTTPNotFound, HTTPBadRequest, HTTPFound
29 from pyramid.httpexceptions import HTTPNotFound, HTTPBadRequest, HTTPFound
30 from pyramid.view import view_config
30 from pyramid.view import view_config
31 from pyramid.renderers import render
31 from pyramid.renderers import render
32 from pyramid.response import Response
32 from pyramid.response import Response
33
33
34 import rhodecode
34 import rhodecode
35 from rhodecode.apps._base import RepoAppView
35 from rhodecode.apps._base import RepoAppView
36
36
37
37
38 from rhodecode.lib import diffs, helpers as h, rc_cache
38 from rhodecode.lib import diffs, helpers as h, rc_cache
39 from rhodecode.lib import audit_logger
39 from rhodecode.lib import audit_logger
40 from rhodecode.lib.view_utils import parse_path_ref
40 from rhodecode.lib.view_utils import parse_path_ref
41 from rhodecode.lib.exceptions import NonRelativePathError
41 from rhodecode.lib.exceptions import NonRelativePathError
42 from rhodecode.lib.codeblocks import (
42 from rhodecode.lib.codeblocks import (
43 filenode_as_lines_tokens, filenode_as_annotated_lines_tokens)
43 filenode_as_lines_tokens, filenode_as_annotated_lines_tokens)
44 from rhodecode.lib.utils2 import (
44 from rhodecode.lib.utils2 import (
45 convert_line_endings, detect_mode, safe_str, str2bool, safe_int)
45 convert_line_endings, detect_mode, safe_str, str2bool, safe_int)
46 from rhodecode.lib.auth import (
46 from rhodecode.lib.auth import (
47 LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired)
47 LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired)
48 from rhodecode.lib.vcs import path as vcspath
48 from rhodecode.lib.vcs import path as vcspath
49 from rhodecode.lib.vcs.backends.base import EmptyCommit
49 from rhodecode.lib.vcs.backends.base import EmptyCommit
50 from rhodecode.lib.vcs.conf import settings
50 from rhodecode.lib.vcs.conf import settings
51 from rhodecode.lib.vcs.nodes import FileNode
51 from rhodecode.lib.vcs.nodes import FileNode
52 from rhodecode.lib.vcs.exceptions import (
52 from rhodecode.lib.vcs.exceptions import (
53 RepositoryError, CommitDoesNotExistError, EmptyRepositoryError,
53 RepositoryError, CommitDoesNotExistError, EmptyRepositoryError,
54 ImproperArchiveTypeError, VCSError, NodeAlreadyExistsError,
54 ImproperArchiveTypeError, VCSError, NodeAlreadyExistsError,
55 NodeDoesNotExistError, CommitError, NodeError)
55 NodeDoesNotExistError, CommitError, NodeError)
56
56
57 from rhodecode.model.scm import ScmModel
57 from rhodecode.model.scm import ScmModel
58 from rhodecode.model.db import Repository
58 from rhodecode.model.db import Repository
59
59
60 log = logging.getLogger(__name__)
60 log = logging.getLogger(__name__)
61
61
62
62
63 class RepoFilesView(RepoAppView):
63 class RepoFilesView(RepoAppView):
64
64
65 @staticmethod
65 @staticmethod
66 def adjust_file_path_for_svn(f_path, repo):
66 def adjust_file_path_for_svn(f_path, repo):
67 """
67 """
68 Computes the relative path of `f_path`.
68 Computes the relative path of `f_path`.
69
69
70 This is mainly based on prefix matching of the recognized tags and
70 This is mainly based on prefix matching of the recognized tags and
71 branches in the underlying repository.
71 branches in the underlying repository.
72 """
72 """
73 tags_and_branches = itertools.chain(
73 tags_and_branches = itertools.chain(
74 repo.branches.iterkeys(),
74 repo.branches.iterkeys(),
75 repo.tags.iterkeys())
75 repo.tags.iterkeys())
76 tags_and_branches = sorted(tags_and_branches, key=len, reverse=True)
76 tags_and_branches = sorted(tags_and_branches, key=len, reverse=True)
77
77
78 for name in tags_and_branches:
78 for name in tags_and_branches:
79 if f_path.startswith('{}/'.format(name)):
79 if f_path.startswith('{}/'.format(name)):
80 f_path = vcspath.relpath(f_path, name)
80 f_path = vcspath.relpath(f_path, name)
81 break
81 break
82 return f_path
82 return f_path
83
83
84 def load_default_context(self):
84 def load_default_context(self):
85 c = self._get_local_tmpl_context(include_app_defaults=True)
85 c = self._get_local_tmpl_context(include_app_defaults=True)
86 c.rhodecode_repo = self.rhodecode_vcs_repo
86 c.rhodecode_repo = self.rhodecode_vcs_repo
87 c.enable_downloads = self.db_repo.enable_downloads
87 c.enable_downloads = self.db_repo.enable_downloads
88 return c
88 return c
89
89
90 def _ensure_not_locked(self):
90 def _ensure_not_locked(self):
91 _ = self.request.translate
91 _ = self.request.translate
92
92
93 repo = self.db_repo
93 repo = self.db_repo
94 if repo.enable_locking and repo.locked[0]:
94 if repo.enable_locking and repo.locked[0]:
95 h.flash(_('This repository has been locked by %s on %s')
95 h.flash(_('This repository has been locked by %s on %s')
96 % (h.person_by_id(repo.locked[0]),
96 % (h.person_by_id(repo.locked[0]),
97 h.format_date(h.time_to_datetime(repo.locked[1]))),
97 h.format_date(h.time_to_datetime(repo.locked[1]))),
98 'warning')
98 'warning')
99 files_url = h.route_path(
99 files_url = h.route_path(
100 'repo_files:default_path',
100 'repo_files:default_path',
101 repo_name=self.db_repo_name, commit_id='tip')
101 repo_name=self.db_repo_name, commit_id='tip')
102 raise HTTPFound(files_url)
102 raise HTTPFound(files_url)
103
103
104 def check_branch_permission(self, branch_name):
104 def check_branch_permission(self, branch_name):
105 _ = self.request.translate
105 _ = self.request.translate
106
106
107 rule, branch_perm = self._rhodecode_user.get_rule_and_branch_permission(
107 rule, branch_perm = self._rhodecode_user.get_rule_and_branch_permission(
108 self.db_repo_name, branch_name)
108 self.db_repo_name, branch_name)
109 if branch_perm and branch_perm not in ['branch.push', 'branch.push_force']:
109 if branch_perm and branch_perm not in ['branch.push', 'branch.push_force']:
110 h.flash(
110 h.flash(
111 _('Branch `{}` changes forbidden by rule {}.').format(branch_name, rule),
111 _('Branch `{}` changes forbidden by rule {}.').format(branch_name, rule),
112 'warning')
112 'warning')
113 files_url = h.route_path(
113 files_url = h.route_path(
114 'repo_files:default_path',
114 'repo_files:default_path',
115 repo_name=self.db_repo_name, commit_id='tip')
115 repo_name=self.db_repo_name, commit_id='tip')
116 raise HTTPFound(files_url)
116 raise HTTPFound(files_url)
117
117
118 def _get_commit_and_path(self):
118 def _get_commit_and_path(self):
119 default_commit_id = self.db_repo.landing_rev[1]
119 default_commit_id = self.db_repo.landing_rev[1]
120 default_f_path = '/'
120 default_f_path = '/'
121
121
122 commit_id = self.request.matchdict.get(
122 commit_id = self.request.matchdict.get(
123 'commit_id', default_commit_id)
123 'commit_id', default_commit_id)
124 f_path = self._get_f_path(self.request.matchdict, default_f_path)
124 f_path = self._get_f_path(self.request.matchdict, default_f_path)
125 return commit_id, f_path
125 return commit_id, f_path
126
126
127 def _get_default_encoding(self, c):
127 def _get_default_encoding(self, c):
128 enc_list = getattr(c, 'default_encodings', [])
128 enc_list = getattr(c, 'default_encodings', [])
129 return enc_list[0] if enc_list else 'UTF-8'
129 return enc_list[0] if enc_list else 'UTF-8'
130
130
131 def _get_commit_or_redirect(self, commit_id, redirect_after=True):
131 def _get_commit_or_redirect(self, commit_id, redirect_after=True):
132 """
132 """
133 This is a safe way to get commit. If an error occurs it redirects to
133 This is a safe way to get commit. If an error occurs it redirects to
134 tip with proper message
134 tip with proper message
135
135
136 :param commit_id: id of commit to fetch
136 :param commit_id: id of commit to fetch
137 :param redirect_after: toggle redirection
137 :param redirect_after: toggle redirection
138 """
138 """
139 _ = self.request.translate
139 _ = self.request.translate
140
140
141 try:
141 try:
142 return self.rhodecode_vcs_repo.get_commit(commit_id)
142 return self.rhodecode_vcs_repo.get_commit(commit_id)
143 except EmptyRepositoryError:
143 except EmptyRepositoryError:
144 if not redirect_after:
144 if not redirect_after:
145 return None
145 return None
146
146
147 _url = h.route_path(
147 _url = h.route_path(
148 'repo_files_add_file',
148 'repo_files_add_file',
149 repo_name=self.db_repo_name, commit_id=0, f_path='',
149 repo_name=self.db_repo_name, commit_id=0, f_path='',
150 _anchor='edit')
150 _anchor='edit')
151
151
152 if h.HasRepoPermissionAny(
152 if h.HasRepoPermissionAny(
153 'repository.write', 'repository.admin')(self.db_repo_name):
153 'repository.write', 'repository.admin')(self.db_repo_name):
154 add_new = h.link_to(
154 add_new = h.link_to(
155 _('Click here to add a new file.'), _url, class_="alert-link")
155 _('Click here to add a new file.'), _url, class_="alert-link")
156 else:
156 else:
157 add_new = ""
157 add_new = ""
158
158
159 h.flash(h.literal(
159 h.flash(h.literal(
160 _('There are no files yet. %s') % add_new), category='warning')
160 _('There are no files yet. %s') % add_new), category='warning')
161 raise HTTPFound(
161 raise HTTPFound(
162 h.route_path('repo_summary', repo_name=self.db_repo_name))
162 h.route_path('repo_summary', repo_name=self.db_repo_name))
163
163
164 except (CommitDoesNotExistError, LookupError):
164 except (CommitDoesNotExistError, LookupError):
165 msg = _('No such commit exists for this repository')
165 msg = _('No such commit exists for this repository')
166 h.flash(msg, category='error')
166 h.flash(msg, category='error')
167 raise HTTPNotFound()
167 raise HTTPNotFound()
168 except RepositoryError as e:
168 except RepositoryError as e:
169 h.flash(safe_str(h.escape(e)), category='error')
169 h.flash(safe_str(h.escape(e)), category='error')
170 raise HTTPNotFound()
170 raise HTTPNotFound()
171
171
172 def _get_filenode_or_redirect(self, commit_obj, path):
172 def _get_filenode_or_redirect(self, commit_obj, path):
173 """
173 """
174 Returns file_node, if error occurs or given path is directory,
174 Returns file_node, if error occurs or given path is directory,
175 it'll redirect to top level path
175 it'll redirect to top level path
176 """
176 """
177 _ = self.request.translate
177 _ = self.request.translate
178
178
179 try:
179 try:
180 file_node = commit_obj.get_node(path)
180 file_node = commit_obj.get_node(path)
181 if file_node.is_dir():
181 if file_node.is_dir():
182 raise RepositoryError('The given path is a directory')
182 raise RepositoryError('The given path is a directory')
183 except CommitDoesNotExistError:
183 except CommitDoesNotExistError:
184 log.exception('No such commit exists for this repository')
184 log.exception('No such commit exists for this repository')
185 h.flash(_('No such commit exists for this repository'), category='error')
185 h.flash(_('No such commit exists for this repository'), category='error')
186 raise HTTPNotFound()
186 raise HTTPNotFound()
187 except RepositoryError as e:
187 except RepositoryError as e:
188 log.warning('Repository error while fetching '
188 log.warning('Repository error while fetching '
189 'filenode `%s`. Err:%s', path, e)
189 'filenode `%s`. Err:%s', path, e)
190 h.flash(safe_str(h.escape(e)), category='error')
190 h.flash(safe_str(h.escape(e)), category='error')
191 raise HTTPNotFound()
191 raise HTTPNotFound()
192
192
193 return file_node
193 return file_node
194
194
195 def _is_valid_head(self, commit_id, repo):
195 def _is_valid_head(self, commit_id, repo):
196 branch_name = sha_commit_id = ''
196 branch_name = sha_commit_id = ''
197 is_head = False
197 is_head = False
198
198
199 if h.is_svn(repo) and not repo.is_empty():
199 if h.is_svn(repo) and not repo.is_empty():
200 # Note: Subversion only has one head.
200 # Note: Subversion only has one head.
201 if commit_id == repo.get_commit(commit_idx=-1).raw_id:
201 if commit_id == repo.get_commit(commit_idx=-1).raw_id:
202 is_head = True
202 is_head = True
203 return branch_name, sha_commit_id, is_head
203 return branch_name, sha_commit_id, is_head
204
204
205 for _branch_name, branch_commit_id in repo.branches.items():
205 for _branch_name, branch_commit_id in repo.branches.items():
206 # simple case we pass in branch name, it's a HEAD
206 # simple case we pass in branch name, it's a HEAD
207 if commit_id == _branch_name:
207 if commit_id == _branch_name:
208 is_head = True
208 is_head = True
209 branch_name = _branch_name
209 branch_name = _branch_name
210 sha_commit_id = branch_commit_id
210 sha_commit_id = branch_commit_id
211 break
211 break
212 # case when we pass in full sha commit_id, which is a head
212 # case when we pass in full sha commit_id, which is a head
213 elif commit_id == branch_commit_id:
213 elif commit_id == branch_commit_id:
214 is_head = True
214 is_head = True
215 branch_name = _branch_name
215 branch_name = _branch_name
216 sha_commit_id = branch_commit_id
216 sha_commit_id = branch_commit_id
217 break
217 break
218
218
219 # checked branches, means we only need to try to get the branch/commit_sha
219 # checked branches, means we only need to try to get the branch/commit_sha
220 if not repo.is_empty:
220 if not repo.is_empty:
221 commit = repo.get_commit(commit_id=commit_id)
221 commit = repo.get_commit(commit_id=commit_id)
222 if commit:
222 if commit:
223 branch_name = commit.branch
223 branch_name = commit.branch
224 sha_commit_id = commit.raw_id
224 sha_commit_id = commit.raw_id
225
225
226 return branch_name, sha_commit_id, is_head
226 return branch_name, sha_commit_id, is_head
227
227
228 def _get_tree_at_commit(self, c, commit_id, f_path, full_load=False):
228 def _get_tree_at_commit(self, c, commit_id, f_path, full_load=False):
229
229
230 repo_id = self.db_repo.repo_id
230 repo_id = self.db_repo.repo_id
231 force_recache = self.get_recache_flag()
231 force_recache = self.get_recache_flag()
232
232
233 cache_seconds = safe_int(
233 cache_seconds = safe_int(
234 rhodecode.CONFIG.get('rc_cache.cache_repo.expiration_time'))
234 rhodecode.CONFIG.get('rc_cache.cache_repo.expiration_time'))
235 cache_on = not force_recache and cache_seconds > 0
235 cache_on = not force_recache and cache_seconds > 0
236 log.debug(
236 log.debug(
237 'Computing FILE TREE for repo_id %s commit_id `%s` and path `%s`'
237 'Computing FILE TREE for repo_id %s commit_id `%s` and path `%s`'
238 'with caching: %s[TTL: %ss]' % (
238 'with caching: %s[TTL: %ss]' % (
239 repo_id, commit_id, f_path, cache_on, cache_seconds or 0))
239 repo_id, commit_id, f_path, cache_on, cache_seconds or 0))
240
240
241 cache_namespace_uid = 'cache_repo.{}'.format(repo_id)
241 cache_namespace_uid = 'cache_repo.{}'.format(repo_id)
242 region = rc_cache.get_or_create_region('cache_repo', cache_namespace_uid)
242 region = rc_cache.get_or_create_region('cache_repo', cache_namespace_uid)
243
243
244 @region.conditional_cache_on_arguments(namespace=cache_namespace_uid,
244 @region.conditional_cache_on_arguments(namespace=cache_namespace_uid,
245 condition=cache_on)
245 condition=cache_on)
246 def compute_file_tree(repo_id, commit_id, f_path, full_load):
246 def compute_file_tree(repo_id, commit_id, f_path, full_load):
247 log.debug('Generating cached file tree for repo_id: %s, %s, %s',
247 log.debug('Generating cached file tree for repo_id: %s, %s, %s',
248 repo_id, commit_id, f_path)
248 repo_id, commit_id, f_path)
249
249
250 c.full_load = full_load
250 c.full_load = full_load
251 return render(
251 return render(
252 'rhodecode:templates/files/files_browser_tree.mako',
252 'rhodecode:templates/files/files_browser_tree.mako',
253 self._get_template_context(c), self.request)
253 self._get_template_context(c), self.request)
254
254
255 return compute_file_tree(self.db_repo.repo_id, commit_id, f_path, full_load)
255 return compute_file_tree(self.db_repo.repo_id, commit_id, f_path, full_load)
256
256
257 def _get_archive_spec(self, fname):
257 def _get_archive_spec(self, fname):
258 log.debug('Detecting archive spec for: `%s`', fname)
258 log.debug('Detecting archive spec for: `%s`', fname)
259
259
260 fileformat = None
260 fileformat = None
261 ext = None
261 ext = None
262 content_type = None
262 content_type = None
263 for a_type, ext_data in settings.ARCHIVE_SPECS.items():
263 for a_type, ext_data in settings.ARCHIVE_SPECS.items():
264 content_type, extension = ext_data
264 content_type, extension = ext_data
265
265
266 if fname.endswith(extension):
266 if fname.endswith(extension):
267 fileformat = a_type
267 fileformat = a_type
268 log.debug('archive is of type: %s', fileformat)
268 log.debug('archive is of type: %s', fileformat)
269 ext = extension
269 ext = extension
270 break
270 break
271
271
272 if not fileformat:
272 if not fileformat:
273 raise ValueError()
273 raise ValueError()
274
274
275 # left over part of whole fname is the commit
275 # left over part of whole fname is the commit
276 commit_id = fname[:-len(ext)]
276 commit_id = fname[:-len(ext)]
277
277
278 return commit_id, ext, fileformat, content_type
278 return commit_id, ext, fileformat, content_type
279
279
280 @LoginRequired()
280 @LoginRequired()
281 @HasRepoPermissionAnyDecorator(
281 @HasRepoPermissionAnyDecorator(
282 'repository.read', 'repository.write', 'repository.admin')
282 'repository.read', 'repository.write', 'repository.admin')
283 @view_config(
283 @view_config(
284 route_name='repo_archivefile', request_method='GET',
284 route_name='repo_archivefile', request_method='GET',
285 renderer=None)
285 renderer=None)
286 def repo_archivefile(self):
286 def repo_archivefile(self):
287 # archive cache config
287 # archive cache config
288 from rhodecode import CONFIG
288 from rhodecode import CONFIG
289 _ = self.request.translate
289 _ = self.request.translate
290 self.load_default_context()
290 self.load_default_context()
291
291
292 fname = self.request.matchdict['fname']
292 fname = self.request.matchdict['fname']
293 subrepos = self.request.GET.get('subrepos') == 'true'
293 subrepos = self.request.GET.get('subrepos') == 'true'
294
294
295 if not self.db_repo.enable_downloads:
295 if not self.db_repo.enable_downloads:
296 return Response(_('Downloads disabled'))
296 return Response(_('Downloads disabled'))
297
297
298 try:
298 try:
299 commit_id, ext, fileformat, content_type = \
299 commit_id, ext, fileformat, content_type = \
300 self._get_archive_spec(fname)
300 self._get_archive_spec(fname)
301 except ValueError:
301 except ValueError:
302 return Response(_('Unknown archive type for: `{}`').format(
302 return Response(_('Unknown archive type for: `{}`').format(
303 h.escape(fname)))
303 h.escape(fname)))
304
304
305 try:
305 try:
306 commit = self.rhodecode_vcs_repo.get_commit(commit_id)
306 commit = self.rhodecode_vcs_repo.get_commit(commit_id)
307 except CommitDoesNotExistError:
307 except CommitDoesNotExistError:
308 return Response(_('Unknown commit_id {}').format(
308 return Response(_('Unknown commit_id {}').format(
309 h.escape(commit_id)))
309 h.escape(commit_id)))
310 except EmptyRepositoryError:
310 except EmptyRepositoryError:
311 return Response(_('Empty repository'))
311 return Response(_('Empty repository'))
312
312
313 archive_name = '%s-%s%s%s' % (
313 archive_name = '%s-%s%s%s' % (
314 safe_str(self.db_repo_name.replace('/', '_')),
314 safe_str(self.db_repo_name.replace('/', '_')),
315 '-sub' if subrepos else '',
315 '-sub' if subrepos else '',
316 safe_str(commit.short_id), ext)
316 safe_str(commit.short_id), ext)
317
317
318 use_cached_archive = False
318 use_cached_archive = False
319 archive_cache_enabled = CONFIG.get(
319 archive_cache_enabled = CONFIG.get(
320 'archive_cache_dir') and not self.request.GET.get('no_cache')
320 'archive_cache_dir') and not self.request.GET.get('no_cache')
321 cached_archive_path = None
321 cached_archive_path = None
322
322
323 if archive_cache_enabled:
323 if archive_cache_enabled:
324 # check if we it's ok to write
324 # check if we it's ok to write
325 if not os.path.isdir(CONFIG['archive_cache_dir']):
325 if not os.path.isdir(CONFIG['archive_cache_dir']):
326 os.makedirs(CONFIG['archive_cache_dir'])
326 os.makedirs(CONFIG['archive_cache_dir'])
327 cached_archive_path = os.path.join(
327 cached_archive_path = os.path.join(
328 CONFIG['archive_cache_dir'], archive_name)
328 CONFIG['archive_cache_dir'], archive_name)
329 if os.path.isfile(cached_archive_path):
329 if os.path.isfile(cached_archive_path):
330 log.debug('Found cached archive in %s', cached_archive_path)
330 log.debug('Found cached archive in %s', cached_archive_path)
331 fd, archive = None, cached_archive_path
331 fd, archive = None, cached_archive_path
332 use_cached_archive = True
332 use_cached_archive = True
333 else:
333 else:
334 log.debug('Archive %s is not yet cached', archive_name)
334 log.debug('Archive %s is not yet cached', archive_name)
335
335
336 if not use_cached_archive:
336 if not use_cached_archive:
337 # generate new archive
337 # generate new archive
338 fd, archive = tempfile.mkstemp()
338 fd, archive = tempfile.mkstemp()
339 log.debug('Creating new temp archive in %s', archive)
339 log.debug('Creating new temp archive in %s', archive)
340 try:
340 try:
341 commit.archive_repo(archive, kind=fileformat, subrepos=subrepos)
341 commit.archive_repo(archive, kind=fileformat, subrepos=subrepos)
342 except ImproperArchiveTypeError:
342 except ImproperArchiveTypeError:
343 return _('Unknown archive type')
343 return _('Unknown archive type')
344 if archive_cache_enabled:
344 if archive_cache_enabled:
345 # if we generated the archive and we have cache enabled
345 # if we generated the archive and we have cache enabled
346 # let's use this for future
346 # let's use this for future
347 log.debug('Storing new archive in %s', cached_archive_path)
347 log.debug('Storing new archive in %s', cached_archive_path)
348 shutil.move(archive, cached_archive_path)
348 shutil.move(archive, cached_archive_path)
349 archive = cached_archive_path
349 archive = cached_archive_path
350
350
351 # store download action
351 # store download action
352 audit_logger.store_web(
352 audit_logger.store_web(
353 'repo.archive.download', action_data={
353 'repo.archive.download', action_data={
354 'user_agent': self.request.user_agent,
354 'user_agent': self.request.user_agent,
355 'archive_name': archive_name,
355 'archive_name': archive_name,
356 'archive_spec': fname,
356 'archive_spec': fname,
357 'archive_cached': use_cached_archive},
357 'archive_cached': use_cached_archive},
358 user=self._rhodecode_user,
358 user=self._rhodecode_user,
359 repo=self.db_repo,
359 repo=self.db_repo,
360 commit=True
360 commit=True
361 )
361 )
362
362
363 def get_chunked_archive(archive_path):
363 def get_chunked_archive(archive_path):
364 with open(archive_path, 'rb') as stream:
364 with open(archive_path, 'rb') as stream:
365 while True:
365 while True:
366 data = stream.read(16 * 1024)
366 data = stream.read(16 * 1024)
367 if not data:
367 if not data:
368 if fd: # fd means we used temporary file
368 if fd: # fd means we used temporary file
369 os.close(fd)
369 os.close(fd)
370 if not archive_cache_enabled:
370 if not archive_cache_enabled:
371 log.debug('Destroying temp archive %s', archive_path)
371 log.debug('Destroying temp archive %s', archive_path)
372 os.remove(archive_path)
372 os.remove(archive_path)
373 break
373 break
374 yield data
374 yield data
375
375
376 response = Response(app_iter=get_chunked_archive(archive))
376 response = Response(app_iter=get_chunked_archive(archive))
377 response.content_disposition = str(
377 response.content_disposition = str(
378 'attachment; filename=%s' % archive_name)
378 'attachment; filename=%s' % archive_name)
379 response.content_type = str(content_type)
379 response.content_type = str(content_type)
380
380
381 return response
381 return response
382
382
383 def _get_file_node(self, commit_id, f_path):
383 def _get_file_node(self, commit_id, f_path):
384 if commit_id not in ['', None, 'None', '0' * 12, '0' * 40]:
384 if commit_id not in ['', None, 'None', '0' * 12, '0' * 40]:
385 commit = self.rhodecode_vcs_repo.get_commit(commit_id=commit_id)
385 commit = self.rhodecode_vcs_repo.get_commit(commit_id=commit_id)
386 try:
386 try:
387 node = commit.get_node(f_path)
387 node = commit.get_node(f_path)
388 if node.is_dir():
388 if node.is_dir():
389 raise NodeError('%s path is a %s not a file'
389 raise NodeError('%s path is a %s not a file'
390 % (node, type(node)))
390 % (node, type(node)))
391 except NodeDoesNotExistError:
391 except NodeDoesNotExistError:
392 commit = EmptyCommit(
392 commit = EmptyCommit(
393 commit_id=commit_id,
393 commit_id=commit_id,
394 idx=commit.idx,
394 idx=commit.idx,
395 repo=commit.repository,
395 repo=commit.repository,
396 alias=commit.repository.alias,
396 alias=commit.repository.alias,
397 message=commit.message,
397 message=commit.message,
398 author=commit.author,
398 author=commit.author,
399 date=commit.date)
399 date=commit.date)
400 node = FileNode(f_path, '', commit=commit)
400 node = FileNode(f_path, '', commit=commit)
401 else:
401 else:
402 commit = EmptyCommit(
402 commit = EmptyCommit(
403 repo=self.rhodecode_vcs_repo,
403 repo=self.rhodecode_vcs_repo,
404 alias=self.rhodecode_vcs_repo.alias)
404 alias=self.rhodecode_vcs_repo.alias)
405 node = FileNode(f_path, '', commit=commit)
405 node = FileNode(f_path, '', commit=commit)
406 return node
406 return node
407
407
408 @LoginRequired()
408 @LoginRequired()
409 @HasRepoPermissionAnyDecorator(
409 @HasRepoPermissionAnyDecorator(
410 'repository.read', 'repository.write', 'repository.admin')
410 'repository.read', 'repository.write', 'repository.admin')
411 @view_config(
411 @view_config(
412 route_name='repo_files_diff', request_method='GET',
412 route_name='repo_files_diff', request_method='GET',
413 renderer=None)
413 renderer=None)
414 def repo_files_diff(self):
414 def repo_files_diff(self):
415 c = self.load_default_context()
415 c = self.load_default_context()
416 f_path = self._get_f_path(self.request.matchdict)
416 f_path = self._get_f_path(self.request.matchdict)
417 diff1 = self.request.GET.get('diff1', '')
417 diff1 = self.request.GET.get('diff1', '')
418 diff2 = self.request.GET.get('diff2', '')
418 diff2 = self.request.GET.get('diff2', '')
419
419
420 path1, diff1 = parse_path_ref(diff1, default_path=f_path)
420 path1, diff1 = parse_path_ref(diff1, default_path=f_path)
421
421
422 ignore_whitespace = str2bool(self.request.GET.get('ignorews'))
422 ignore_whitespace = str2bool(self.request.GET.get('ignorews'))
423 line_context = self.request.GET.get('context', 3)
423 line_context = self.request.GET.get('context', 3)
424
424
425 if not any((diff1, diff2)):
425 if not any((diff1, diff2)):
426 h.flash(
426 h.flash(
427 'Need query parameter "diff1" or "diff2" to generate a diff.',
427 'Need query parameter "diff1" or "diff2" to generate a diff.',
428 category='error')
428 category='error')
429 raise HTTPBadRequest()
429 raise HTTPBadRequest()
430
430
431 c.action = self.request.GET.get('diff')
431 c.action = self.request.GET.get('diff')
432 if c.action not in ['download', 'raw']:
432 if c.action not in ['download', 'raw']:
433 compare_url = h.route_path(
433 compare_url = h.route_path(
434 'repo_compare',
434 'repo_compare',
435 repo_name=self.db_repo_name,
435 repo_name=self.db_repo_name,
436 source_ref_type='rev',
436 source_ref_type='rev',
437 source_ref=diff1,
437 source_ref=diff1,
438 target_repo=self.db_repo_name,
438 target_repo=self.db_repo_name,
439 target_ref_type='rev',
439 target_ref_type='rev',
440 target_ref=diff2,
440 target_ref=diff2,
441 _query=dict(f_path=f_path))
441 _query=dict(f_path=f_path))
442 # redirect to new view if we render diff
442 # redirect to new view if we render diff
443 raise HTTPFound(compare_url)
443 raise HTTPFound(compare_url)
444
444
445 try:
445 try:
446 node1 = self._get_file_node(diff1, path1)
446 node1 = self._get_file_node(diff1, path1)
447 node2 = self._get_file_node(diff2, f_path)
447 node2 = self._get_file_node(diff2, f_path)
448 except (RepositoryError, NodeError):
448 except (RepositoryError, NodeError):
449 log.exception("Exception while trying to get node from repository")
449 log.exception("Exception while trying to get node from repository")
450 raise HTTPFound(
450 raise HTTPFound(
451 h.route_path('repo_files', repo_name=self.db_repo_name,
451 h.route_path('repo_files', repo_name=self.db_repo_name,
452 commit_id='tip', f_path=f_path))
452 commit_id='tip', f_path=f_path))
453
453
454 if all(isinstance(node.commit, EmptyCommit)
454 if all(isinstance(node.commit, EmptyCommit)
455 for node in (node1, node2)):
455 for node in (node1, node2)):
456 raise HTTPNotFound()
456 raise HTTPNotFound()
457
457
458 c.commit_1 = node1.commit
458 c.commit_1 = node1.commit
459 c.commit_2 = node2.commit
459 c.commit_2 = node2.commit
460
460
461 if c.action == 'download':
461 if c.action == 'download':
462 _diff = diffs.get_gitdiff(node1, node2,
462 _diff = diffs.get_gitdiff(node1, node2,
463 ignore_whitespace=ignore_whitespace,
463 ignore_whitespace=ignore_whitespace,
464 context=line_context)
464 context=line_context)
465 diff = diffs.DiffProcessor(_diff, format='gitdiff')
465 diff = diffs.DiffProcessor(_diff, format='gitdiff')
466
466
467 response = Response(self.path_filter.get_raw_patch(diff))
467 response = Response(self.path_filter.get_raw_patch(diff))
468 response.content_type = 'text/plain'
468 response.content_type = 'text/plain'
469 response.content_disposition = (
469 response.content_disposition = (
470 'attachment; filename=%s_%s_vs_%s.diff' % (f_path, diff1, diff2)
470 'attachment; filename=%s_%s_vs_%s.diff' % (f_path, diff1, diff2)
471 )
471 )
472 charset = self._get_default_encoding(c)
472 charset = self._get_default_encoding(c)
473 if charset:
473 if charset:
474 response.charset = charset
474 response.charset = charset
475 return response
475 return response
476
476
477 elif c.action == 'raw':
477 elif c.action == 'raw':
478 _diff = diffs.get_gitdiff(node1, node2,
478 _diff = diffs.get_gitdiff(node1, node2,
479 ignore_whitespace=ignore_whitespace,
479 ignore_whitespace=ignore_whitespace,
480 context=line_context)
480 context=line_context)
481 diff = diffs.DiffProcessor(_diff, format='gitdiff')
481 diff = diffs.DiffProcessor(_diff, format='gitdiff')
482
482
483 response = Response(self.path_filter.get_raw_patch(diff))
483 response = Response(self.path_filter.get_raw_patch(diff))
484 response.content_type = 'text/plain'
484 response.content_type = 'text/plain'
485 charset = self._get_default_encoding(c)
485 charset = self._get_default_encoding(c)
486 if charset:
486 if charset:
487 response.charset = charset
487 response.charset = charset
488 return response
488 return response
489
489
490 # in case we ever end up here
490 # in case we ever end up here
491 raise HTTPNotFound()
491 raise HTTPNotFound()
492
492
493 @LoginRequired()
493 @LoginRequired()
494 @HasRepoPermissionAnyDecorator(
494 @HasRepoPermissionAnyDecorator(
495 'repository.read', 'repository.write', 'repository.admin')
495 'repository.read', 'repository.write', 'repository.admin')
496 @view_config(
496 @view_config(
497 route_name='repo_files_diff_2way_redirect', request_method='GET',
497 route_name='repo_files_diff_2way_redirect', request_method='GET',
498 renderer=None)
498 renderer=None)
499 def repo_files_diff_2way_redirect(self):
499 def repo_files_diff_2way_redirect(self):
500 """
500 """
501 Kept only to make OLD links work
501 Kept only to make OLD links work
502 """
502 """
503 f_path = self._get_f_path_unchecked(self.request.matchdict)
503 f_path = self._get_f_path_unchecked(self.request.matchdict)
504 diff1 = self.request.GET.get('diff1', '')
504 diff1 = self.request.GET.get('diff1', '')
505 diff2 = self.request.GET.get('diff2', '')
505 diff2 = self.request.GET.get('diff2', '')
506
506
507 if not any((diff1, diff2)):
507 if not any((diff1, diff2)):
508 h.flash(
508 h.flash(
509 'Need query parameter "diff1" or "diff2" to generate a diff.',
509 'Need query parameter "diff1" or "diff2" to generate a diff.',
510 category='error')
510 category='error')
511 raise HTTPBadRequest()
511 raise HTTPBadRequest()
512
512
513 compare_url = h.route_path(
513 compare_url = h.route_path(
514 'repo_compare',
514 'repo_compare',
515 repo_name=self.db_repo_name,
515 repo_name=self.db_repo_name,
516 source_ref_type='rev',
516 source_ref_type='rev',
517 source_ref=diff1,
517 source_ref=diff1,
518 target_ref_type='rev',
518 target_ref_type='rev',
519 target_ref=diff2,
519 target_ref=diff2,
520 _query=dict(f_path=f_path, diffmode='sideside',
520 _query=dict(f_path=f_path, diffmode='sideside',
521 target_repo=self.db_repo_name,))
521 target_repo=self.db_repo_name,))
522 raise HTTPFound(compare_url)
522 raise HTTPFound(compare_url)
523
523
524 @LoginRequired()
524 @LoginRequired()
525 @HasRepoPermissionAnyDecorator(
525 @HasRepoPermissionAnyDecorator(
526 'repository.read', 'repository.write', 'repository.admin')
526 'repository.read', 'repository.write', 'repository.admin')
527 @view_config(
527 @view_config(
528 route_name='repo_files', request_method='GET',
528 route_name='repo_files', request_method='GET',
529 renderer=None)
529 renderer=None)
530 @view_config(
530 @view_config(
531 route_name='repo_files:default_path', request_method='GET',
531 route_name='repo_files:default_path', request_method='GET',
532 renderer=None)
532 renderer=None)
533 @view_config(
533 @view_config(
534 route_name='repo_files:default_commit', request_method='GET',
534 route_name='repo_files:default_commit', request_method='GET',
535 renderer=None)
535 renderer=None)
536 @view_config(
536 @view_config(
537 route_name='repo_files:rendered', request_method='GET',
537 route_name='repo_files:rendered', request_method='GET',
538 renderer=None)
538 renderer=None)
539 @view_config(
539 @view_config(
540 route_name='repo_files:annotated', request_method='GET',
540 route_name='repo_files:annotated', request_method='GET',
541 renderer=None)
541 renderer=None)
542 def repo_files(self):
542 def repo_files(self):
543 c = self.load_default_context()
543 c = self.load_default_context()
544
544
545 view_name = getattr(self.request.matched_route, 'name', None)
545 view_name = getattr(self.request.matched_route, 'name', None)
546
546
547 c.annotate = view_name == 'repo_files:annotated'
547 c.annotate = view_name == 'repo_files:annotated'
548 # default is false, but .rst/.md files later are auto rendered, we can
548 # default is false, but .rst/.md files later are auto rendered, we can
549 # overwrite auto rendering by setting this GET flag
549 # overwrite auto rendering by setting this GET flag
550 c.renderer = view_name == 'repo_files:rendered' or \
550 c.renderer = view_name == 'repo_files:rendered' or \
551 not self.request.GET.get('no-render', False)
551 not self.request.GET.get('no-render', False)
552
552
553 # redirect to given commit_id from form if given
553 # redirect to given commit_id from form if given
554 get_commit_id = self.request.GET.get('at_rev', None)
554 get_commit_id = self.request.GET.get('at_rev', None)
555 if get_commit_id:
555 if get_commit_id:
556 self._get_commit_or_redirect(get_commit_id)
556 self._get_commit_or_redirect(get_commit_id)
557
557
558 commit_id, f_path = self._get_commit_and_path()
558 commit_id, f_path = self._get_commit_and_path()
559 c.commit = self._get_commit_or_redirect(commit_id)
559 c.commit = self._get_commit_or_redirect(commit_id)
560 c.branch = self.request.GET.get('branch', None)
560 c.branch = self.request.GET.get('branch', None)
561 c.f_path = f_path
561 c.f_path = f_path
562
562
563 # prev link
563 # prev link
564 try:
564 try:
565 prev_commit = c.commit.prev(c.branch)
565 prev_commit = c.commit.prev(c.branch)
566 c.prev_commit = prev_commit
566 c.prev_commit = prev_commit
567 c.url_prev = h.route_path(
567 c.url_prev = h.route_path(
568 'repo_files', repo_name=self.db_repo_name,
568 'repo_files', repo_name=self.db_repo_name,
569 commit_id=prev_commit.raw_id, f_path=f_path)
569 commit_id=prev_commit.raw_id, f_path=f_path)
570 if c.branch:
570 if c.branch:
571 c.url_prev += '?branch=%s' % c.branch
571 c.url_prev += '?branch=%s' % c.branch
572 except (CommitDoesNotExistError, VCSError):
572 except (CommitDoesNotExistError, VCSError):
573 c.url_prev = '#'
573 c.url_prev = '#'
574 c.prev_commit = EmptyCommit()
574 c.prev_commit = EmptyCommit()
575
575
576 # next link
576 # next link
577 try:
577 try:
578 next_commit = c.commit.next(c.branch)
578 next_commit = c.commit.next(c.branch)
579 c.next_commit = next_commit
579 c.next_commit = next_commit
580 c.url_next = h.route_path(
580 c.url_next = h.route_path(
581 'repo_files', repo_name=self.db_repo_name,
581 'repo_files', repo_name=self.db_repo_name,
582 commit_id=next_commit.raw_id, f_path=f_path)
582 commit_id=next_commit.raw_id, f_path=f_path)
583 if c.branch:
583 if c.branch:
584 c.url_next += '?branch=%s' % c.branch
584 c.url_next += '?branch=%s' % c.branch
585 except (CommitDoesNotExistError, VCSError):
585 except (CommitDoesNotExistError, VCSError):
586 c.url_next = '#'
586 c.url_next = '#'
587 c.next_commit = EmptyCommit()
587 c.next_commit = EmptyCommit()
588
588
589 # files or dirs
589 # files or dirs
590 try:
590 try:
591 c.file = c.commit.get_node(f_path)
591 c.file = c.commit.get_node(f_path)
592 c.file_author = True
592 c.file_author = True
593 c.file_tree = ''
593 c.file_tree = ''
594
594
595 # load file content
595 # load file content
596 if c.file.is_file():
596 if c.file.is_file():
597 c.lf_node = c.file.get_largefile_node()
597 c.lf_node = c.file.get_largefile_node()
598
598
599 c.file_source_page = 'true'
599 c.file_source_page = 'true'
600 c.file_last_commit = c.file.last_commit
600 c.file_last_commit = c.file.last_commit
601 if c.file.size < c.visual.cut_off_limit_diff:
601 if c.file.size < c.visual.cut_off_limit_diff:
602 if c.annotate: # annotation has precedence over renderer
602 if c.annotate: # annotation has precedence over renderer
603 c.annotated_lines = filenode_as_annotated_lines_tokens(
603 c.annotated_lines = filenode_as_annotated_lines_tokens(
604 c.file
604 c.file
605 )
605 )
606 else:
606 else:
607 c.renderer = (
607 c.renderer = (
608 c.renderer and h.renderer_from_filename(c.file.path)
608 c.renderer and h.renderer_from_filename(c.file.path)
609 )
609 )
610 if not c.renderer:
610 if not c.renderer:
611 c.lines = filenode_as_lines_tokens(c.file)
611 c.lines = filenode_as_lines_tokens(c.file)
612
612
613 _branch_name, _sha_commit_id, is_head = self._is_valid_head(
613 _branch_name, _sha_commit_id, is_head = self._is_valid_head(
614 commit_id, self.rhodecode_vcs_repo)
614 commit_id, self.rhodecode_vcs_repo)
615 c.on_branch_head = is_head
615 c.on_branch_head = is_head
616
616
617 branch = c.commit.branch if (
617 branch = c.commit.branch if (
618 c.commit.branch and '/' not in c.commit.branch) else None
618 c.commit.branch and '/' not in c.commit.branch) else None
619 c.branch_or_raw_id = branch or c.commit.raw_id
619 c.branch_or_raw_id = branch or c.commit.raw_id
620 c.branch_name = c.commit.branch or h.short_id(c.commit.raw_id)
620 c.branch_name = c.commit.branch or h.short_id(c.commit.raw_id)
621
621
622 author = c.file_last_commit.author
622 author = c.file_last_commit.author
623 c.authors = [[
623 c.authors = [[
624 h.email(author),
624 h.email(author),
625 h.person(author, 'username_or_name_or_email'),
625 h.person(author, 'username_or_name_or_email'),
626 1
626 1
627 ]]
627 ]]
628
628
629 else: # load tree content at path
629 else: # load tree content at path
630 c.file_source_page = 'false'
630 c.file_source_page = 'false'
631 c.authors = []
631 c.authors = []
632 # this loads a simple tree without metadata to speed things up
632 # this loads a simple tree without metadata to speed things up
633 # later via ajax we call repo_nodetree_full and fetch whole
633 # later via ajax we call repo_nodetree_full and fetch whole
634 c.file_tree = self._get_tree_at_commit(c, c.commit.raw_id, f_path)
634 c.file_tree = self._get_tree_at_commit(c, c.commit.raw_id, f_path)
635
635
636 except RepositoryError as e:
636 except RepositoryError as e:
637 h.flash(safe_str(h.escape(e)), category='error')
637 h.flash(safe_str(h.escape(e)), category='error')
638 raise HTTPNotFound()
638 raise HTTPNotFound()
639
639
640 if self.request.environ.get('HTTP_X_PJAX'):
640 if self.request.environ.get('HTTP_X_PJAX'):
641 html = render('rhodecode:templates/files/files_pjax.mako',
641 html = render('rhodecode:templates/files/files_pjax.mako',
642 self._get_template_context(c), self.request)
642 self._get_template_context(c), self.request)
643 else:
643 else:
644 html = render('rhodecode:templates/files/files.mako',
644 html = render('rhodecode:templates/files/files.mako',
645 self._get_template_context(c), self.request)
645 self._get_template_context(c), self.request)
646 return Response(html)
646 return Response(html)
647
647
648 @HasRepoPermissionAnyDecorator(
648 @HasRepoPermissionAnyDecorator(
649 'repository.read', 'repository.write', 'repository.admin')
649 'repository.read', 'repository.write', 'repository.admin')
650 @view_config(
650 @view_config(
651 route_name='repo_files:annotated_previous', request_method='GET',
651 route_name='repo_files:annotated_previous', request_method='GET',
652 renderer=None)
652 renderer=None)
653 def repo_files_annotated_previous(self):
653 def repo_files_annotated_previous(self):
654 self.load_default_context()
654 self.load_default_context()
655
655
656 commit_id, f_path = self._get_commit_and_path()
656 commit_id, f_path = self._get_commit_and_path()
657 commit = self._get_commit_or_redirect(commit_id)
657 commit = self._get_commit_or_redirect(commit_id)
658 prev_commit_id = commit.raw_id
658 prev_commit_id = commit.raw_id
659 line_anchor = self.request.GET.get('line_anchor')
659 line_anchor = self.request.GET.get('line_anchor')
660 is_file = False
660 is_file = False
661 try:
661 try:
662 _file = commit.get_node(f_path)
662 _file = commit.get_node(f_path)
663 is_file = _file.is_file()
663 is_file = _file.is_file()
664 except (NodeDoesNotExistError, CommitDoesNotExistError, VCSError):
664 except (NodeDoesNotExistError, CommitDoesNotExistError, VCSError):
665 pass
665 pass
666
666
667 if is_file:
667 if is_file:
668 history = commit.get_path_history(f_path)
668 history = commit.get_path_history(f_path)
669 prev_commit_id = history[1].raw_id \
669 prev_commit_id = history[1].raw_id \
670 if len(history) > 1 else prev_commit_id
670 if len(history) > 1 else prev_commit_id
671 prev_url = h.route_path(
671 prev_url = h.route_path(
672 'repo_files:annotated', repo_name=self.db_repo_name,
672 'repo_files:annotated', repo_name=self.db_repo_name,
673 commit_id=prev_commit_id, f_path=f_path,
673 commit_id=prev_commit_id, f_path=f_path,
674 _anchor='L{}'.format(line_anchor))
674 _anchor='L{}'.format(line_anchor))
675
675
676 raise HTTPFound(prev_url)
676 raise HTTPFound(prev_url)
677
677
678 @LoginRequired()
678 @LoginRequired()
679 @HasRepoPermissionAnyDecorator(
679 @HasRepoPermissionAnyDecorator(
680 'repository.read', 'repository.write', 'repository.admin')
680 'repository.read', 'repository.write', 'repository.admin')
681 @view_config(
681 @view_config(
682 route_name='repo_nodetree_full', request_method='GET',
682 route_name='repo_nodetree_full', request_method='GET',
683 renderer=None, xhr=True)
683 renderer=None, xhr=True)
684 @view_config(
684 @view_config(
685 route_name='repo_nodetree_full:default_path', request_method='GET',
685 route_name='repo_nodetree_full:default_path', request_method='GET',
686 renderer=None, xhr=True)
686 renderer=None, xhr=True)
687 def repo_nodetree_full(self):
687 def repo_nodetree_full(self):
688 """
688 """
689 Returns rendered html of file tree that contains commit date,
689 Returns rendered html of file tree that contains commit date,
690 author, commit_id for the specified combination of
690 author, commit_id for the specified combination of
691 repo, commit_id and file path
691 repo, commit_id and file path
692 """
692 """
693 c = self.load_default_context()
693 c = self.load_default_context()
694
694
695 commit_id, f_path = self._get_commit_and_path()
695 commit_id, f_path = self._get_commit_and_path()
696 commit = self._get_commit_or_redirect(commit_id)
696 commit = self._get_commit_or_redirect(commit_id)
697 try:
697 try:
698 dir_node = commit.get_node(f_path)
698 dir_node = commit.get_node(f_path)
699 except RepositoryError as e:
699 except RepositoryError as e:
700 return Response('error: {}'.format(h.escape(safe_str(e))))
700 return Response('error: {}'.format(h.escape(safe_str(e))))
701
701
702 if dir_node.is_file():
702 if dir_node.is_file():
703 return Response('')
703 return Response('')
704
704
705 c.file = dir_node
705 c.file = dir_node
706 c.commit = commit
706 c.commit = commit
707
707
708 html = self._get_tree_at_commit(
708 html = self._get_tree_at_commit(
709 c, commit.raw_id, dir_node.path, full_load=True)
709 c, commit.raw_id, dir_node.path, full_load=True)
710
710
711 return Response(html)
711 return Response(html)
712
712
713 def _get_attachement_headers(self, f_path):
713 def _get_attachement_headers(self, f_path):
714 f_name = safe_str(f_path.split(Repository.NAME_SEP)[-1])
714 f_name = safe_str(f_path.split(Repository.NAME_SEP)[-1])
715 safe_path = f_name.replace('"', '\\"')
715 safe_path = f_name.replace('"', '\\"')
716 encoded_path = urllib.quote(f_name)
716 encoded_path = urllib.quote(f_name)
717
717
718 return "attachment; " \
718 return "attachment; " \
719 "filename=\"{}\"; " \
719 "filename=\"{}\"; " \
720 "filename*=UTF-8\'\'{}".format(safe_path, encoded_path)
720 "filename*=UTF-8\'\'{}".format(safe_path, encoded_path)
721
721
722 @LoginRequired()
722 @LoginRequired()
723 @HasRepoPermissionAnyDecorator(
723 @HasRepoPermissionAnyDecorator(
724 'repository.read', 'repository.write', 'repository.admin')
724 'repository.read', 'repository.write', 'repository.admin')
725 @view_config(
725 @view_config(
726 route_name='repo_file_raw', request_method='GET',
726 route_name='repo_file_raw', request_method='GET',
727 renderer=None)
727 renderer=None)
728 def repo_file_raw(self):
728 def repo_file_raw(self):
729 """
729 """
730 Action for show as raw, some mimetypes are "rendered",
730 Action for show as raw, some mimetypes are "rendered",
731 those include images, icons.
731 those include images, icons.
732 """
732 """
733 c = self.load_default_context()
733 c = self.load_default_context()
734
734
735 commit_id, f_path = self._get_commit_and_path()
735 commit_id, f_path = self._get_commit_and_path()
736 commit = self._get_commit_or_redirect(commit_id)
736 commit = self._get_commit_or_redirect(commit_id)
737 file_node = self._get_filenode_or_redirect(commit, f_path)
737 file_node = self._get_filenode_or_redirect(commit, f_path)
738
738
739 raw_mimetype_mapping = {
739 raw_mimetype_mapping = {
740 # map original mimetype to a mimetype used for "show as raw"
740 # map original mimetype to a mimetype used for "show as raw"
741 # you can also provide a content-disposition to override the
741 # you can also provide a content-disposition to override the
742 # default "attachment" disposition.
742 # default "attachment" disposition.
743 # orig_type: (new_type, new_dispo)
743 # orig_type: (new_type, new_dispo)
744
744
745 # show images inline:
745 # show images inline:
746 # Do not re-add SVG: it is unsafe and permits XSS attacks. One can
746 # Do not re-add SVG: it is unsafe and permits XSS attacks. One can
747 # for example render an SVG with javascript inside or even render
747 # for example render an SVG with javascript inside or even render
748 # HTML.
748 # HTML.
749 'image/x-icon': ('image/x-icon', 'inline'),
749 'image/x-icon': ('image/x-icon', 'inline'),
750 'image/png': ('image/png', 'inline'),
750 'image/png': ('image/png', 'inline'),
751 'image/gif': ('image/gif', 'inline'),
751 'image/gif': ('image/gif', 'inline'),
752 'image/jpeg': ('image/jpeg', 'inline'),
752 'image/jpeg': ('image/jpeg', 'inline'),
753 'application/pdf': ('application/pdf', 'inline'),
753 'application/pdf': ('application/pdf', 'inline'),
754 }
754 }
755
755
756 mimetype = file_node.mimetype
756 mimetype = file_node.mimetype
757 try:
757 try:
758 mimetype, disposition = raw_mimetype_mapping[mimetype]
758 mimetype, disposition = raw_mimetype_mapping[mimetype]
759 except KeyError:
759 except KeyError:
760 # we don't know anything special about this, handle it safely
760 # we don't know anything special about this, handle it safely
761 if file_node.is_binary:
761 if file_node.is_binary:
762 # do same as download raw for binary files
762 # do same as download raw for binary files
763 mimetype, disposition = 'application/octet-stream', 'attachment'
763 mimetype, disposition = 'application/octet-stream', 'attachment'
764 else:
764 else:
765 # do not just use the original mimetype, but force text/plain,
765 # do not just use the original mimetype, but force text/plain,
766 # otherwise it would serve text/html and that might be unsafe.
766 # otherwise it would serve text/html and that might be unsafe.
767 # Note: underlying vcs library fakes text/plain mimetype if the
767 # Note: underlying vcs library fakes text/plain mimetype if the
768 # mimetype can not be determined and it thinks it is not
768 # mimetype can not be determined and it thinks it is not
769 # binary.This might lead to erroneous text display in some
769 # binary.This might lead to erroneous text display in some
770 # cases, but helps in other cases, like with text files
770 # cases, but helps in other cases, like with text files
771 # without extension.
771 # without extension.
772 mimetype, disposition = 'text/plain', 'inline'
772 mimetype, disposition = 'text/plain', 'inline'
773
773
774 if disposition == 'attachment':
774 if disposition == 'attachment':
775 disposition = self._get_attachement_headers(f_path)
775 disposition = self._get_attachement_headers(f_path)
776
776
777 def stream_node():
777 def stream_node():
778 yield file_node.raw_bytes
778 yield file_node.raw_bytes
779
779
780 response = Response(app_iter=stream_node())
780 response = Response(app_iter=stream_node())
781 response.content_disposition = disposition
781 response.content_disposition = disposition
782 response.content_type = mimetype
782 response.content_type = mimetype
783
783
784 charset = self._get_default_encoding(c)
784 charset = self._get_default_encoding(c)
785 if charset:
785 if charset:
786 response.charset = charset
786 response.charset = charset
787
787
788 return response
788 return response
789
789
790 @LoginRequired()
790 @LoginRequired()
791 @HasRepoPermissionAnyDecorator(
791 @HasRepoPermissionAnyDecorator(
792 'repository.read', 'repository.write', 'repository.admin')
792 'repository.read', 'repository.write', 'repository.admin')
793 @view_config(
793 @view_config(
794 route_name='repo_file_download', request_method='GET',
794 route_name='repo_file_download', request_method='GET',
795 renderer=None)
795 renderer=None)
796 @view_config(
796 @view_config(
797 route_name='repo_file_download:legacy', request_method='GET',
797 route_name='repo_file_download:legacy', request_method='GET',
798 renderer=None)
798 renderer=None)
799 def repo_file_download(self):
799 def repo_file_download(self):
800 c = self.load_default_context()
800 c = self.load_default_context()
801
801
802 commit_id, f_path = self._get_commit_and_path()
802 commit_id, f_path = self._get_commit_and_path()
803 commit = self._get_commit_or_redirect(commit_id)
803 commit = self._get_commit_or_redirect(commit_id)
804 file_node = self._get_filenode_or_redirect(commit, f_path)
804 file_node = self._get_filenode_or_redirect(commit, f_path)
805
805
806 if self.request.GET.get('lf'):
806 if self.request.GET.get('lf'):
807 # only if lf get flag is passed, we download this file
807 # only if lf get flag is passed, we download this file
808 # as LFS/Largefile
808 # as LFS/Largefile
809 lf_node = file_node.get_largefile_node()
809 lf_node = file_node.get_largefile_node()
810 if lf_node:
810 if lf_node:
811 # overwrite our pointer with the REAL large-file
811 # overwrite our pointer with the REAL large-file
812 file_node = lf_node
812 file_node = lf_node
813
813
814 disposition = self._get_attachement_headers(f_path)
814 disposition = self._get_attachement_headers(f_path)
815
815
816 def stream_node():
816 def stream_node():
817 yield file_node.raw_bytes
817 yield file_node.raw_bytes
818
818
819 response = Response(app_iter=stream_node())
819 response = Response(app_iter=stream_node())
820 response.content_disposition = disposition
820 response.content_disposition = disposition
821 response.content_type = file_node.mimetype
821 response.content_type = file_node.mimetype
822
822
823 charset = self._get_default_encoding(c)
823 charset = self._get_default_encoding(c)
824 if charset:
824 if charset:
825 response.charset = charset
825 response.charset = charset
826
826
827 return response
827 return response
828
828
829 def _get_nodelist_at_commit(self, repo_name, repo_id, commit_id, f_path):
829 def _get_nodelist_at_commit(self, repo_name, repo_id, commit_id, f_path):
830
830
831 cache_seconds = safe_int(
831 cache_seconds = safe_int(
832 rhodecode.CONFIG.get('rc_cache.cache_repo.expiration_time'))
832 rhodecode.CONFIG.get('rc_cache.cache_repo.expiration_time'))
833 cache_on = cache_seconds > 0
833 cache_on = cache_seconds > 0
834 log.debug(
834 log.debug(
835 'Computing FILE SEARCH for repo_id %s commit_id `%s` and path `%s`'
835 'Computing FILE SEARCH for repo_id %s commit_id `%s` and path `%s`'
836 'with caching: %s[TTL: %ss]' % (
836 'with caching: %s[TTL: %ss]' % (
837 repo_id, commit_id, f_path, cache_on, cache_seconds or 0))
837 repo_id, commit_id, f_path, cache_on, cache_seconds or 0))
838
838
839 cache_namespace_uid = 'cache_repo.{}'.format(repo_id)
839 cache_namespace_uid = 'cache_repo.{}'.format(repo_id)
840 region = rc_cache.get_or_create_region('cache_repo', cache_namespace_uid)
840 region = rc_cache.get_or_create_region('cache_repo', cache_namespace_uid)
841
841
842 @region.conditional_cache_on_arguments(namespace=cache_namespace_uid,
842 @region.conditional_cache_on_arguments(namespace=cache_namespace_uid,
843 condition=cache_on)
843 condition=cache_on)
844 def compute_file_search(repo_id, commit_id, f_path):
844 def compute_file_search(repo_id, commit_id, f_path):
845 log.debug('Generating cached nodelist for repo_id:%s, %s, %s',
845 log.debug('Generating cached nodelist for repo_id:%s, %s, %s',
846 repo_id, commit_id, f_path)
846 repo_id, commit_id, f_path)
847 try:
847 try:
848 _d, _f = ScmModel().get_nodes(
848 _d, _f = ScmModel().get_nodes(
849 repo_name, commit_id, f_path, flat=False)
849 repo_name, commit_id, f_path, flat=False)
850 except (RepositoryError, CommitDoesNotExistError, Exception) as e:
850 except (RepositoryError, CommitDoesNotExistError, Exception) as e:
851 log.exception(safe_str(e))
851 log.exception(safe_str(e))
852 h.flash(safe_str(h.escape(e)), category='error')
852 h.flash(safe_str(h.escape(e)), category='error')
853 raise HTTPFound(h.route_path(
853 raise HTTPFound(h.route_path(
854 'repo_files', repo_name=self.db_repo_name,
854 'repo_files', repo_name=self.db_repo_name,
855 commit_id='tip', f_path='/'))
855 commit_id='tip', f_path='/'))
856 return _d + _f
856 return _d + _f
857
857
858 return compute_file_search(self.db_repo.repo_id, commit_id, f_path)
858 return compute_file_search(self.db_repo.repo_id, commit_id, f_path)
859
859
860 @LoginRequired()
860 @LoginRequired()
861 @HasRepoPermissionAnyDecorator(
861 @HasRepoPermissionAnyDecorator(
862 'repository.read', 'repository.write', 'repository.admin')
862 'repository.read', 'repository.write', 'repository.admin')
863 @view_config(
863 @view_config(
864 route_name='repo_files_nodelist', request_method='GET',
864 route_name='repo_files_nodelist', request_method='GET',
865 renderer='json_ext', xhr=True)
865 renderer='json_ext', xhr=True)
866 def repo_nodelist(self):
866 def repo_nodelist(self):
867 self.load_default_context()
867 self.load_default_context()
868
868
869 commit_id, f_path = self._get_commit_and_path()
869 commit_id, f_path = self._get_commit_and_path()
870 commit = self._get_commit_or_redirect(commit_id)
870 commit = self._get_commit_or_redirect(commit_id)
871
871
872 metadata = self._get_nodelist_at_commit(
872 metadata = self._get_nodelist_at_commit(
873 self.db_repo_name, self.db_repo.repo_id, commit.raw_id, f_path)
873 self.db_repo_name, self.db_repo.repo_id, commit.raw_id, f_path)
874 return {'nodes': metadata}
874 return {'nodes': metadata}
875
875
876 def _create_references(
876 def _create_references(self, branches_or_tags, symbolic_reference, f_path, ref_type):
877 self, branches_or_tags, symbolic_reference, f_path):
878 items = []
877 items = []
879 for name, commit_id in branches_or_tags.items():
878 for name, commit_id in branches_or_tags.items():
880 sym_ref = symbolic_reference(commit_id, name, f_path)
879 sym_ref = symbolic_reference(commit_id, name, f_path, ref_type)
881 items.append((sym_ref, name))
880 items.append((sym_ref, name, ref_type))
882 return items
881 return items
883
882
884 def _symbolic_reference(self, commit_id, name, f_path):
883 def _symbolic_reference(self, commit_id, name, f_path, ref_type):
885 return commit_id
884 return commit_id
886
885
887 def _symbolic_reference_svn(self, commit_id, name, f_path):
886 def _symbolic_reference_svn(self, commit_id, name, f_path, ref_type):
888 new_f_path = vcspath.join(name, f_path)
887 new_f_path = vcspath.join(name, f_path)
889 return u'%s@%s' % (new_f_path, commit_id)
888 return u'%s@%s' % (new_f_path, commit_id)
890
889
891 def _get_node_history(self, commit_obj, f_path, commits=None):
890 def _get_node_history(self, commit_obj, f_path, commits=None):
892 """
891 """
893 get commit history for given node
892 get commit history for given node
894
893
895 :param commit_obj: commit to calculate history
894 :param commit_obj: commit to calculate history
896 :param f_path: path for node to calculate history for
895 :param f_path: path for node to calculate history for
897 :param commits: if passed don't calculate history and take
896 :param commits: if passed don't calculate history and take
898 commits defined in this list
897 commits defined in this list
899 """
898 """
900 _ = self.request.translate
899 _ = self.request.translate
901
900
902 # calculate history based on tip
901 # calculate history based on tip
903 tip = self.rhodecode_vcs_repo.get_commit()
902 tip = self.rhodecode_vcs_repo.get_commit()
904 if commits is None:
903 if commits is None:
905 pre_load = ["author", "branch"]
904 pre_load = ["author", "branch"]
906 try:
905 try:
907 commits = tip.get_path_history(f_path, pre_load=pre_load)
906 commits = tip.get_path_history(f_path, pre_load=pre_load)
908 except (NodeDoesNotExistError, CommitError):
907 except (NodeDoesNotExistError, CommitError):
909 # this node is not present at tip!
908 # this node is not present at tip!
910 commits = commit_obj.get_path_history(f_path, pre_load=pre_load)
909 commits = commit_obj.get_path_history(f_path, pre_load=pre_load)
911
910
912 history = []
911 history = []
913 commits_group = ([], _("Changesets"))
912 commits_group = ([], _("Changesets"))
914 for commit in commits:
913 for commit in commits:
915 branch = ' (%s)' % commit.branch if commit.branch else ''
914 branch = ' (%s)' % commit.branch if commit.branch else ''
916 n_desc = 'r%s:%s%s' % (commit.idx, commit.short_id, branch)
915 n_desc = 'r%s:%s%s' % (commit.idx, commit.short_id, branch)
917 commits_group[0].append((commit.raw_id, n_desc,))
916 commits_group[0].append((commit.raw_id, n_desc, 'sha'))
918 history.append(commits_group)
917 history.append(commits_group)
919
918
920 symbolic_reference = self._symbolic_reference
919 symbolic_reference = self._symbolic_reference
921
920
922 if self.rhodecode_vcs_repo.alias == 'svn':
921 if self.rhodecode_vcs_repo.alias == 'svn':
923 adjusted_f_path = RepoFilesView.adjust_file_path_for_svn(
922 adjusted_f_path = RepoFilesView.adjust_file_path_for_svn(
924 f_path, self.rhodecode_vcs_repo)
923 f_path, self.rhodecode_vcs_repo)
925 if adjusted_f_path != f_path:
924 if adjusted_f_path != f_path:
926 log.debug(
925 log.debug(
927 'Recognized svn tag or branch in file "%s", using svn '
926 'Recognized svn tag or branch in file "%s", using svn '
928 'specific symbolic references', f_path)
927 'specific symbolic references', f_path)
929 f_path = adjusted_f_path
928 f_path = adjusted_f_path
930 symbolic_reference = self._symbolic_reference_svn
929 symbolic_reference = self._symbolic_reference_svn
931
930
932 branches = self._create_references(
931 branches = self._create_references(
933 self.rhodecode_vcs_repo.branches, symbolic_reference, f_path)
932 self.rhodecode_vcs_repo.branches, symbolic_reference, f_path, 'branch')
934 branches_group = (branches, _("Branches"))
933 branches_group = (branches, _("Branches"))
935
934
936 tags = self._create_references(
935 tags = self._create_references(
937 self.rhodecode_vcs_repo.tags, symbolic_reference, f_path)
936 self.rhodecode_vcs_repo.tags, symbolic_reference, f_path, 'tag')
938 tags_group = (tags, _("Tags"))
937 tags_group = (tags, _("Tags"))
939
938
940 history.append(branches_group)
939 history.append(branches_group)
941 history.append(tags_group)
940 history.append(tags_group)
942
941
943 return history, commits
942 return history, commits
944
943
945 @LoginRequired()
944 @LoginRequired()
946 @HasRepoPermissionAnyDecorator(
945 @HasRepoPermissionAnyDecorator(
947 'repository.read', 'repository.write', 'repository.admin')
946 'repository.read', 'repository.write', 'repository.admin')
948 @view_config(
947 @view_config(
949 route_name='repo_file_history', request_method='GET',
948 route_name='repo_file_history', request_method='GET',
950 renderer='json_ext')
949 renderer='json_ext')
951 def repo_file_history(self):
950 def repo_file_history(self):
952 self.load_default_context()
951 self.load_default_context()
953
952
954 commit_id, f_path = self._get_commit_and_path()
953 commit_id, f_path = self._get_commit_and_path()
955 commit = self._get_commit_or_redirect(commit_id)
954 commit = self._get_commit_or_redirect(commit_id)
956 file_node = self._get_filenode_or_redirect(commit, f_path)
955 file_node = self._get_filenode_or_redirect(commit, f_path)
957
956
958 if file_node.is_file():
957 if file_node.is_file():
959 file_history, _hist = self._get_node_history(commit, f_path)
958 file_history, _hist = self._get_node_history(commit, f_path)
960
959
961 res = []
960 res = []
962 for obj in file_history:
961 for obj in file_history:
963 res.append({
962 res.append({
964 'text': obj[1],
963 'text': obj[1],
965 'children': [{'id': o[0], 'text': o[1]} for o in obj[0]]
964 'children': [{'id': o[0], 'text': o[1], 'type': o[2]} for o in obj[0]]
966 })
965 })
967
966
968 data = {
967 data = {
969 'more': False,
968 'more': False,
970 'results': res
969 'results': res
971 }
970 }
972 return data
971 return data
973
972
974 log.warning('Cannot fetch history for directory')
973 log.warning('Cannot fetch history for directory')
975 raise HTTPBadRequest()
974 raise HTTPBadRequest()
976
975
977 @LoginRequired()
976 @LoginRequired()
978 @HasRepoPermissionAnyDecorator(
977 @HasRepoPermissionAnyDecorator(
979 'repository.read', 'repository.write', 'repository.admin')
978 'repository.read', 'repository.write', 'repository.admin')
980 @view_config(
979 @view_config(
981 route_name='repo_file_authors', request_method='GET',
980 route_name='repo_file_authors', request_method='GET',
982 renderer='rhodecode:templates/files/file_authors_box.mako')
981 renderer='rhodecode:templates/files/file_authors_box.mako')
983 def repo_file_authors(self):
982 def repo_file_authors(self):
984 c = self.load_default_context()
983 c = self.load_default_context()
985
984
986 commit_id, f_path = self._get_commit_and_path()
985 commit_id, f_path = self._get_commit_and_path()
987 commit = self._get_commit_or_redirect(commit_id)
986 commit = self._get_commit_or_redirect(commit_id)
988 file_node = self._get_filenode_or_redirect(commit, f_path)
987 file_node = self._get_filenode_or_redirect(commit, f_path)
989
988
990 if not file_node.is_file():
989 if not file_node.is_file():
991 raise HTTPBadRequest()
990 raise HTTPBadRequest()
992
991
993 c.file_last_commit = file_node.last_commit
992 c.file_last_commit = file_node.last_commit
994 if self.request.GET.get('annotate') == '1':
993 if self.request.GET.get('annotate') == '1':
995 # use _hist from annotation if annotation mode is on
994 # use _hist from annotation if annotation mode is on
996 commit_ids = set(x[1] for x in file_node.annotate)
995 commit_ids = set(x[1] for x in file_node.annotate)
997 _hist = (
996 _hist = (
998 self.rhodecode_vcs_repo.get_commit(commit_id)
997 self.rhodecode_vcs_repo.get_commit(commit_id)
999 for commit_id in commit_ids)
998 for commit_id in commit_ids)
1000 else:
999 else:
1001 _f_history, _hist = self._get_node_history(commit, f_path)
1000 _f_history, _hist = self._get_node_history(commit, f_path)
1002 c.file_author = False
1001 c.file_author = False
1003
1002
1004 unique = collections.OrderedDict()
1003 unique = collections.OrderedDict()
1005 for commit in _hist:
1004 for commit in _hist:
1006 author = commit.author
1005 author = commit.author
1007 if author not in unique:
1006 if author not in unique:
1008 unique[commit.author] = [
1007 unique[commit.author] = [
1009 h.email(author),
1008 h.email(author),
1010 h.person(author, 'username_or_name_or_email'),
1009 h.person(author, 'username_or_name_or_email'),
1011 1 # counter
1010 1 # counter
1012 ]
1011 ]
1013
1012
1014 else:
1013 else:
1015 # increase counter
1014 # increase counter
1016 unique[commit.author][2] += 1
1015 unique[commit.author][2] += 1
1017
1016
1018 c.authors = [val for val in unique.values()]
1017 c.authors = [val for val in unique.values()]
1019
1018
1020 return self._get_template_context(c)
1019 return self._get_template_context(c)
1021
1020
1022 @LoginRequired()
1021 @LoginRequired()
1023 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
1022 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
1024 @view_config(
1023 @view_config(
1025 route_name='repo_files_remove_file', request_method='GET',
1024 route_name='repo_files_remove_file', request_method='GET',
1026 renderer='rhodecode:templates/files/files_delete.mako')
1025 renderer='rhodecode:templates/files/files_delete.mako')
1027 def repo_files_remove_file(self):
1026 def repo_files_remove_file(self):
1028 _ = self.request.translate
1027 _ = self.request.translate
1029 c = self.load_default_context()
1028 c = self.load_default_context()
1030 commit_id, f_path = self._get_commit_and_path()
1029 commit_id, f_path = self._get_commit_and_path()
1031
1030
1032 self._ensure_not_locked()
1031 self._ensure_not_locked()
1033 _branch_name, _sha_commit_id, is_head = \
1032 _branch_name, _sha_commit_id, is_head = \
1034 self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
1033 self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
1035
1034
1036 if not is_head:
1035 if not is_head:
1037 h.flash(_('You can only delete files with commit '
1036 h.flash(_('You can only delete files with commit '
1038 'being a valid branch head.'), category='warning')
1037 'being a valid branch head.'), category='warning')
1039 raise HTTPFound(
1038 raise HTTPFound(
1040 h.route_path('repo_files',
1039 h.route_path('repo_files',
1041 repo_name=self.db_repo_name, commit_id='tip',
1040 repo_name=self.db_repo_name, commit_id='tip',
1042 f_path=f_path))
1041 f_path=f_path))
1043
1042
1044 self.check_branch_permission(_branch_name)
1043 self.check_branch_permission(_branch_name)
1045 c.commit = self._get_commit_or_redirect(commit_id)
1044 c.commit = self._get_commit_or_redirect(commit_id)
1046 c.file = self._get_filenode_or_redirect(c.commit, f_path)
1045 c.file = self._get_filenode_or_redirect(c.commit, f_path)
1047
1046
1048 c.default_message = _(
1047 c.default_message = _(
1049 'Deleted file {} via RhodeCode Enterprise').format(f_path)
1048 'Deleted file {} via RhodeCode Enterprise').format(f_path)
1050 c.f_path = f_path
1049 c.f_path = f_path
1051
1050
1052 return self._get_template_context(c)
1051 return self._get_template_context(c)
1053
1052
1054 @LoginRequired()
1053 @LoginRequired()
1055 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
1054 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
1056 @CSRFRequired()
1055 @CSRFRequired()
1057 @view_config(
1056 @view_config(
1058 route_name='repo_files_delete_file', request_method='POST',
1057 route_name='repo_files_delete_file', request_method='POST',
1059 renderer=None)
1058 renderer=None)
1060 def repo_files_delete_file(self):
1059 def repo_files_delete_file(self):
1061 _ = self.request.translate
1060 _ = self.request.translate
1062
1061
1063 c = self.load_default_context()
1062 c = self.load_default_context()
1064 commit_id, f_path = self._get_commit_and_path()
1063 commit_id, f_path = self._get_commit_and_path()
1065
1064
1066 self._ensure_not_locked()
1065 self._ensure_not_locked()
1067 _branch_name, _sha_commit_id, is_head = \
1066 _branch_name, _sha_commit_id, is_head = \
1068 self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
1067 self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
1069
1068
1070 if not is_head:
1069 if not is_head:
1071 h.flash(_('You can only delete files with commit '
1070 h.flash(_('You can only delete files with commit '
1072 'being a valid branch head.'), category='warning')
1071 'being a valid branch head.'), category='warning')
1073 raise HTTPFound(
1072 raise HTTPFound(
1074 h.route_path('repo_files',
1073 h.route_path('repo_files',
1075 repo_name=self.db_repo_name, commit_id='tip',
1074 repo_name=self.db_repo_name, commit_id='tip',
1076 f_path=f_path))
1075 f_path=f_path))
1077 self.check_branch_permission(_branch_name)
1076 self.check_branch_permission(_branch_name)
1078
1077
1079 c.commit = self._get_commit_or_redirect(commit_id)
1078 c.commit = self._get_commit_or_redirect(commit_id)
1080 c.file = self._get_filenode_or_redirect(c.commit, f_path)
1079 c.file = self._get_filenode_or_redirect(c.commit, f_path)
1081
1080
1082 c.default_message = _(
1081 c.default_message = _(
1083 'Deleted file {} via RhodeCode Enterprise').format(f_path)
1082 'Deleted file {} via RhodeCode Enterprise').format(f_path)
1084 c.f_path = f_path
1083 c.f_path = f_path
1085 node_path = f_path
1084 node_path = f_path
1086 author = self._rhodecode_db_user.full_contact
1085 author = self._rhodecode_db_user.full_contact
1087 message = self.request.POST.get('message') or c.default_message
1086 message = self.request.POST.get('message') or c.default_message
1088 try:
1087 try:
1089 nodes = {
1088 nodes = {
1090 node_path: {
1089 node_path: {
1091 'content': ''
1090 'content': ''
1092 }
1091 }
1093 }
1092 }
1094 ScmModel().delete_nodes(
1093 ScmModel().delete_nodes(
1095 user=self._rhodecode_db_user.user_id, repo=self.db_repo,
1094 user=self._rhodecode_db_user.user_id, repo=self.db_repo,
1096 message=message,
1095 message=message,
1097 nodes=nodes,
1096 nodes=nodes,
1098 parent_commit=c.commit,
1097 parent_commit=c.commit,
1099 author=author,
1098 author=author,
1100 )
1099 )
1101
1100
1102 h.flash(
1101 h.flash(
1103 _('Successfully deleted file `{}`').format(
1102 _('Successfully deleted file `{}`').format(
1104 h.escape(f_path)), category='success')
1103 h.escape(f_path)), category='success')
1105 except Exception:
1104 except Exception:
1106 log.exception('Error during commit operation')
1105 log.exception('Error during commit operation')
1107 h.flash(_('Error occurred during commit'), category='error')
1106 h.flash(_('Error occurred during commit'), category='error')
1108 raise HTTPFound(
1107 raise HTTPFound(
1109 h.route_path('repo_commit', repo_name=self.db_repo_name,
1108 h.route_path('repo_commit', repo_name=self.db_repo_name,
1110 commit_id='tip'))
1109 commit_id='tip'))
1111
1110
1112 @LoginRequired()
1111 @LoginRequired()
1113 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
1112 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
1114 @view_config(
1113 @view_config(
1115 route_name='repo_files_edit_file', request_method='GET',
1114 route_name='repo_files_edit_file', request_method='GET',
1116 renderer='rhodecode:templates/files/files_edit.mako')
1115 renderer='rhodecode:templates/files/files_edit.mako')
1117 def repo_files_edit_file(self):
1116 def repo_files_edit_file(self):
1118 _ = self.request.translate
1117 _ = self.request.translate
1119 c = self.load_default_context()
1118 c = self.load_default_context()
1120 commit_id, f_path = self._get_commit_and_path()
1119 commit_id, f_path = self._get_commit_and_path()
1121
1120
1122 self._ensure_not_locked()
1121 self._ensure_not_locked()
1123 _branch_name, _sha_commit_id, is_head = \
1122 _branch_name, _sha_commit_id, is_head = \
1124 self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
1123 self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
1125
1124
1126 if not is_head:
1125 if not is_head:
1127 h.flash(_('You can only edit files with commit '
1126 h.flash(_('You can only edit files with commit '
1128 'being a valid branch head.'), category='warning')
1127 'being a valid branch head.'), category='warning')
1129 raise HTTPFound(
1128 raise HTTPFound(
1130 h.route_path('repo_files',
1129 h.route_path('repo_files',
1131 repo_name=self.db_repo_name, commit_id='tip',
1130 repo_name=self.db_repo_name, commit_id='tip',
1132 f_path=f_path))
1131 f_path=f_path))
1133 self.check_branch_permission(_branch_name)
1132 self.check_branch_permission(_branch_name)
1134
1133
1135 c.commit = self._get_commit_or_redirect(commit_id)
1134 c.commit = self._get_commit_or_redirect(commit_id)
1136 c.file = self._get_filenode_or_redirect(c.commit, f_path)
1135 c.file = self._get_filenode_or_redirect(c.commit, f_path)
1137
1136
1138 if c.file.is_binary:
1137 if c.file.is_binary:
1139 files_url = h.route_path(
1138 files_url = h.route_path(
1140 'repo_files',
1139 'repo_files',
1141 repo_name=self.db_repo_name,
1140 repo_name=self.db_repo_name,
1142 commit_id=c.commit.raw_id, f_path=f_path)
1141 commit_id=c.commit.raw_id, f_path=f_path)
1143 raise HTTPFound(files_url)
1142 raise HTTPFound(files_url)
1144
1143
1145 c.default_message = _(
1144 c.default_message = _(
1146 'Edited file {} via RhodeCode Enterprise').format(f_path)
1145 'Edited file {} via RhodeCode Enterprise').format(f_path)
1147 c.f_path = f_path
1146 c.f_path = f_path
1148
1147
1149 return self._get_template_context(c)
1148 return self._get_template_context(c)
1150
1149
1151 @LoginRequired()
1150 @LoginRequired()
1152 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
1151 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
1153 @CSRFRequired()
1152 @CSRFRequired()
1154 @view_config(
1153 @view_config(
1155 route_name='repo_files_update_file', request_method='POST',
1154 route_name='repo_files_update_file', request_method='POST',
1156 renderer=None)
1155 renderer=None)
1157 def repo_files_update_file(self):
1156 def repo_files_update_file(self):
1158 _ = self.request.translate
1157 _ = self.request.translate
1159 c = self.load_default_context()
1158 c = self.load_default_context()
1160 commit_id, f_path = self._get_commit_and_path()
1159 commit_id, f_path = self._get_commit_and_path()
1161
1160
1162 self._ensure_not_locked()
1161 self._ensure_not_locked()
1163 _branch_name, _sha_commit_id, is_head = \
1162 _branch_name, _sha_commit_id, is_head = \
1164 self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
1163 self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
1165
1164
1166 if not is_head:
1165 if not is_head:
1167 h.flash(_('You can only edit files with commit '
1166 h.flash(_('You can only edit files with commit '
1168 'being a valid branch head.'), category='warning')
1167 'being a valid branch head.'), category='warning')
1169 raise HTTPFound(
1168 raise HTTPFound(
1170 h.route_path('repo_files',
1169 h.route_path('repo_files',
1171 repo_name=self.db_repo_name, commit_id='tip',
1170 repo_name=self.db_repo_name, commit_id='tip',
1172 f_path=f_path))
1171 f_path=f_path))
1173
1172
1174 self.check_branch_permission(_branch_name)
1173 self.check_branch_permission(_branch_name)
1175
1174
1176 c.commit = self._get_commit_or_redirect(commit_id)
1175 c.commit = self._get_commit_or_redirect(commit_id)
1177 c.file = self._get_filenode_or_redirect(c.commit, f_path)
1176 c.file = self._get_filenode_or_redirect(c.commit, f_path)
1178
1177
1179 if c.file.is_binary:
1178 if c.file.is_binary:
1180 raise HTTPFound(
1179 raise HTTPFound(
1181 h.route_path('repo_files',
1180 h.route_path('repo_files',
1182 repo_name=self.db_repo_name,
1181 repo_name=self.db_repo_name,
1183 commit_id=c.commit.raw_id,
1182 commit_id=c.commit.raw_id,
1184 f_path=f_path))
1183 f_path=f_path))
1185
1184
1186 c.default_message = _(
1185 c.default_message = _(
1187 'Edited file {} via RhodeCode Enterprise').format(f_path)
1186 'Edited file {} via RhodeCode Enterprise').format(f_path)
1188 c.f_path = f_path
1187 c.f_path = f_path
1189 old_content = c.file.content
1188 old_content = c.file.content
1190 sl = old_content.splitlines(1)
1189 sl = old_content.splitlines(1)
1191 first_line = sl[0] if sl else ''
1190 first_line = sl[0] if sl else ''
1192
1191
1193 r_post = self.request.POST
1192 r_post = self.request.POST
1194 # line endings: 0 - Unix, 1 - Mac, 2 - DOS
1193 # line endings: 0 - Unix, 1 - Mac, 2 - DOS
1195 line_ending_mode = detect_mode(first_line, 0)
1194 line_ending_mode = detect_mode(first_line, 0)
1196 content = convert_line_endings(r_post.get('content', ''), line_ending_mode)
1195 content = convert_line_endings(r_post.get('content', ''), line_ending_mode)
1197
1196
1198 message = r_post.get('message') or c.default_message
1197 message = r_post.get('message') or c.default_message
1199 org_f_path = c.file.unicode_path
1198 org_f_path = c.file.unicode_path
1200 filename = r_post['filename']
1199 filename = r_post['filename']
1201 org_filename = c.file.name
1200 org_filename = c.file.name
1202
1201
1203 if content == old_content and filename == org_filename:
1202 if content == old_content and filename == org_filename:
1204 h.flash(_('No changes'), category='warning')
1203 h.flash(_('No changes'), category='warning')
1205 raise HTTPFound(
1204 raise HTTPFound(
1206 h.route_path('repo_commit', repo_name=self.db_repo_name,
1205 h.route_path('repo_commit', repo_name=self.db_repo_name,
1207 commit_id='tip'))
1206 commit_id='tip'))
1208 try:
1207 try:
1209 mapping = {
1208 mapping = {
1210 org_f_path: {
1209 org_f_path: {
1211 'org_filename': org_f_path,
1210 'org_filename': org_f_path,
1212 'filename': os.path.join(c.file.dir_path, filename),
1211 'filename': os.path.join(c.file.dir_path, filename),
1213 'content': content,
1212 'content': content,
1214 'lexer': '',
1213 'lexer': '',
1215 'op': 'mod',
1214 'op': 'mod',
1216 'mode': c.file.mode
1215 'mode': c.file.mode
1217 }
1216 }
1218 }
1217 }
1219
1218
1220 ScmModel().update_nodes(
1219 ScmModel().update_nodes(
1221 user=self._rhodecode_db_user.user_id,
1220 user=self._rhodecode_db_user.user_id,
1222 repo=self.db_repo,
1221 repo=self.db_repo,
1223 message=message,
1222 message=message,
1224 nodes=mapping,
1223 nodes=mapping,
1225 parent_commit=c.commit,
1224 parent_commit=c.commit,
1226 )
1225 )
1227
1226
1228 h.flash(
1227 h.flash(
1229 _('Successfully committed changes to file `{}`').format(
1228 _('Successfully committed changes to file `{}`').format(
1230 h.escape(f_path)), category='success')
1229 h.escape(f_path)), category='success')
1231 except Exception:
1230 except Exception:
1232 log.exception('Error occurred during commit')
1231 log.exception('Error occurred during commit')
1233 h.flash(_('Error occurred during commit'), category='error')
1232 h.flash(_('Error occurred during commit'), category='error')
1234 raise HTTPFound(
1233 raise HTTPFound(
1235 h.route_path('repo_commit', repo_name=self.db_repo_name,
1234 h.route_path('repo_commit', repo_name=self.db_repo_name,
1236 commit_id='tip'))
1235 commit_id='tip'))
1237
1236
1238 @LoginRequired()
1237 @LoginRequired()
1239 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
1238 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
1240 @view_config(
1239 @view_config(
1241 route_name='repo_files_add_file', request_method='GET',
1240 route_name='repo_files_add_file', request_method='GET',
1242 renderer='rhodecode:templates/files/files_add.mako')
1241 renderer='rhodecode:templates/files/files_add.mako')
1243 def repo_files_add_file(self):
1242 def repo_files_add_file(self):
1244 _ = self.request.translate
1243 _ = self.request.translate
1245 c = self.load_default_context()
1244 c = self.load_default_context()
1246 commit_id, f_path = self._get_commit_and_path()
1245 commit_id, f_path = self._get_commit_and_path()
1247
1246
1248 self._ensure_not_locked()
1247 self._ensure_not_locked()
1249
1248
1250 c.commit = self._get_commit_or_redirect(commit_id, redirect_after=False)
1249 c.commit = self._get_commit_or_redirect(commit_id, redirect_after=False)
1251 if c.commit is None:
1250 if c.commit is None:
1252 c.commit = EmptyCommit(alias=self.rhodecode_vcs_repo.alias)
1251 c.commit = EmptyCommit(alias=self.rhodecode_vcs_repo.alias)
1253 c.default_message = (_('Added file via RhodeCode Enterprise'))
1252 c.default_message = (_('Added file via RhodeCode Enterprise'))
1254 c.f_path = f_path.lstrip('/') # ensure not relative path
1253 c.f_path = f_path.lstrip('/') # ensure not relative path
1255
1254
1256 if self.rhodecode_vcs_repo.is_empty:
1255 if self.rhodecode_vcs_repo.is_empty:
1257 # for empty repository we cannot check for current branch, we rely on
1256 # for empty repository we cannot check for current branch, we rely on
1258 # c.commit.branch instead
1257 # c.commit.branch instead
1259 _branch_name = c.commit.branch
1258 _branch_name = c.commit.branch
1260 is_head = True
1259 is_head = True
1261 else:
1260 else:
1262 _branch_name, _sha_commit_id, is_head = \
1261 _branch_name, _sha_commit_id, is_head = \
1263 self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
1262 self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
1264
1263
1265 if not is_head:
1264 if not is_head:
1266 h.flash(_('You can only add files with commit '
1265 h.flash(_('You can only add files with commit '
1267 'being a valid branch head.'), category='warning')
1266 'being a valid branch head.'), category='warning')
1268 raise HTTPFound(
1267 raise HTTPFound(
1269 h.route_path('repo_files',
1268 h.route_path('repo_files',
1270 repo_name=self.db_repo_name, commit_id='tip',
1269 repo_name=self.db_repo_name, commit_id='tip',
1271 f_path=f_path))
1270 f_path=f_path))
1272
1271
1273 self.check_branch_permission(_branch_name)
1272 self.check_branch_permission(_branch_name)
1274
1273
1275 return self._get_template_context(c)
1274 return self._get_template_context(c)
1276
1275
1277 @LoginRequired()
1276 @LoginRequired()
1278 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
1277 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
1279 @CSRFRequired()
1278 @CSRFRequired()
1280 @view_config(
1279 @view_config(
1281 route_name='repo_files_create_file', request_method='POST',
1280 route_name='repo_files_create_file', request_method='POST',
1282 renderer=None)
1281 renderer=None)
1283 def repo_files_create_file(self):
1282 def repo_files_create_file(self):
1284 _ = self.request.translate
1283 _ = self.request.translate
1285 c = self.load_default_context()
1284 c = self.load_default_context()
1286 commit_id, f_path = self._get_commit_and_path()
1285 commit_id, f_path = self._get_commit_and_path()
1287
1286
1288 self._ensure_not_locked()
1287 self._ensure_not_locked()
1289
1288
1290 r_post = self.request.POST
1289 r_post = self.request.POST
1291
1290
1292 c.commit = self._get_commit_or_redirect(
1291 c.commit = self._get_commit_or_redirect(
1293 commit_id, redirect_after=False)
1292 commit_id, redirect_after=False)
1294 if c.commit is None:
1293 if c.commit is None:
1295 c.commit = EmptyCommit(alias=self.rhodecode_vcs_repo.alias)
1294 c.commit = EmptyCommit(alias=self.rhodecode_vcs_repo.alias)
1296
1295
1297 if self.rhodecode_vcs_repo.is_empty:
1296 if self.rhodecode_vcs_repo.is_empty:
1298 # for empty repository we cannot check for current branch, we rely on
1297 # for empty repository we cannot check for current branch, we rely on
1299 # c.commit.branch instead
1298 # c.commit.branch instead
1300 _branch_name = c.commit.branch
1299 _branch_name = c.commit.branch
1301 is_head = True
1300 is_head = True
1302 else:
1301 else:
1303 _branch_name, _sha_commit_id, is_head = \
1302 _branch_name, _sha_commit_id, is_head = \
1304 self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
1303 self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
1305
1304
1306 if not is_head:
1305 if not is_head:
1307 h.flash(_('You can only add files with commit '
1306 h.flash(_('You can only add files with commit '
1308 'being a valid branch head.'), category='warning')
1307 'being a valid branch head.'), category='warning')
1309 raise HTTPFound(
1308 raise HTTPFound(
1310 h.route_path('repo_files',
1309 h.route_path('repo_files',
1311 repo_name=self.db_repo_name, commit_id='tip',
1310 repo_name=self.db_repo_name, commit_id='tip',
1312 f_path=f_path))
1311 f_path=f_path))
1313
1312
1314 self.check_branch_permission(_branch_name)
1313 self.check_branch_permission(_branch_name)
1315
1314
1316 c.default_message = (_('Added file via RhodeCode Enterprise'))
1315 c.default_message = (_('Added file via RhodeCode Enterprise'))
1317 c.f_path = f_path
1316 c.f_path = f_path
1318 unix_mode = 0
1317 unix_mode = 0
1319 content = convert_line_endings(r_post.get('content', ''), unix_mode)
1318 content = convert_line_endings(r_post.get('content', ''), unix_mode)
1320
1319
1321 message = r_post.get('message') or c.default_message
1320 message = r_post.get('message') or c.default_message
1322 filename = r_post.get('filename')
1321 filename = r_post.get('filename')
1323 location = r_post.get('location', '') # dir location
1322 location = r_post.get('location', '') # dir location
1324 file_obj = r_post.get('upload_file', None)
1323 file_obj = r_post.get('upload_file', None)
1325
1324
1326 if file_obj is not None and hasattr(file_obj, 'filename'):
1325 if file_obj is not None and hasattr(file_obj, 'filename'):
1327 filename = r_post.get('filename_upload')
1326 filename = r_post.get('filename_upload')
1328 content = file_obj.file
1327 content = file_obj.file
1329
1328
1330 if hasattr(content, 'file'):
1329 if hasattr(content, 'file'):
1331 # non posix systems store real file under file attr
1330 # non posix systems store real file under file attr
1332 content = content.file
1331 content = content.file
1333
1332
1334 if self.rhodecode_vcs_repo.is_empty:
1333 if self.rhodecode_vcs_repo.is_empty:
1335 default_redirect_url = h.route_path(
1334 default_redirect_url = h.route_path(
1336 'repo_summary', repo_name=self.db_repo_name)
1335 'repo_summary', repo_name=self.db_repo_name)
1337 else:
1336 else:
1338 default_redirect_url = h.route_path(
1337 default_redirect_url = h.route_path(
1339 'repo_commit', repo_name=self.db_repo_name, commit_id='tip')
1338 'repo_commit', repo_name=self.db_repo_name, commit_id='tip')
1340
1339
1341 # If there's no commit, redirect to repo summary
1340 # If there's no commit, redirect to repo summary
1342 if type(c.commit) is EmptyCommit:
1341 if type(c.commit) is EmptyCommit:
1343 redirect_url = h.route_path(
1342 redirect_url = h.route_path(
1344 'repo_summary', repo_name=self.db_repo_name)
1343 'repo_summary', repo_name=self.db_repo_name)
1345 else:
1344 else:
1346 redirect_url = default_redirect_url
1345 redirect_url = default_redirect_url
1347
1346
1348 if not filename:
1347 if not filename:
1349 h.flash(_('No filename'), category='warning')
1348 h.flash(_('No filename'), category='warning')
1350 raise HTTPFound(redirect_url)
1349 raise HTTPFound(redirect_url)
1351
1350
1352 # extract the location from filename,
1351 # extract the location from filename,
1353 # allows using foo/bar.txt syntax to create subdirectories
1352 # allows using foo/bar.txt syntax to create subdirectories
1354 subdir_loc = filename.rsplit('/', 1)
1353 subdir_loc = filename.rsplit('/', 1)
1355 if len(subdir_loc) == 2:
1354 if len(subdir_loc) == 2:
1356 location = os.path.join(location, subdir_loc[0])
1355 location = os.path.join(location, subdir_loc[0])
1357
1356
1358 # strip all crap out of file, just leave the basename
1357 # strip all crap out of file, just leave the basename
1359 filename = os.path.basename(filename)
1358 filename = os.path.basename(filename)
1360 node_path = os.path.join(location, filename)
1359 node_path = os.path.join(location, filename)
1361 author = self._rhodecode_db_user.full_contact
1360 author = self._rhodecode_db_user.full_contact
1362
1361
1363 try:
1362 try:
1364 nodes = {
1363 nodes = {
1365 node_path: {
1364 node_path: {
1366 'content': content
1365 'content': content
1367 }
1366 }
1368 }
1367 }
1369 ScmModel().create_nodes(
1368 ScmModel().create_nodes(
1370 user=self._rhodecode_db_user.user_id,
1369 user=self._rhodecode_db_user.user_id,
1371 repo=self.db_repo,
1370 repo=self.db_repo,
1372 message=message,
1371 message=message,
1373 nodes=nodes,
1372 nodes=nodes,
1374 parent_commit=c.commit,
1373 parent_commit=c.commit,
1375 author=author,
1374 author=author,
1376 )
1375 )
1377
1376
1378 h.flash(
1377 h.flash(
1379 _('Successfully committed new file `{}`').format(
1378 _('Successfully committed new file `{}`').format(
1380 h.escape(node_path)), category='success')
1379 h.escape(node_path)), category='success')
1381 except NonRelativePathError:
1380 except NonRelativePathError:
1382 log.exception('Non Relative path found')
1381 log.exception('Non Relative path found')
1383 h.flash(_(
1382 h.flash(_(
1384 'The location specified must be a relative path and must not '
1383 'The location specified must be a relative path and must not '
1385 'contain .. in the path'), category='warning')
1384 'contain .. in the path'), category='warning')
1386 raise HTTPFound(default_redirect_url)
1385 raise HTTPFound(default_redirect_url)
1387 except (NodeError, NodeAlreadyExistsError) as e:
1386 except (NodeError, NodeAlreadyExistsError) as e:
1388 h.flash(_(h.escape(e)), category='error')
1387 h.flash(_(h.escape(e)), category='error')
1389 except Exception:
1388 except Exception:
1390 log.exception('Error occurred during commit')
1389 log.exception('Error occurred during commit')
1391 h.flash(_('Error occurred during commit'), category='error')
1390 h.flash(_('Error occurred during commit'), category='error')
1392
1391
1393 raise HTTPFound(default_redirect_url)
1392 raise HTTPFound(default_redirect_url)
@@ -1,2050 +1,2057 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2019 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 """
21 """
22 Helper functions
22 Helper functions
23
23
24 Consists of functions to typically be used within templates, but also
24 Consists of functions to typically be used within templates, but also
25 available to Controllers. This module is available to both as 'h'.
25 available to Controllers. This module is available to both as 'h'.
26 """
26 """
27
27
28 import os
28 import os
29 import random
29 import random
30 import hashlib
30 import hashlib
31 import StringIO
31 import StringIO
32 import textwrap
32 import textwrap
33 import urllib
33 import urllib
34 import math
34 import math
35 import logging
35 import logging
36 import re
36 import re
37 import time
37 import time
38 import string
38 import string
39 import hashlib
39 import hashlib
40 from collections import OrderedDict
40 from collections import OrderedDict
41
41
42 import pygments
42 import pygments
43 import itertools
43 import itertools
44 import fnmatch
44 import fnmatch
45 import bleach
45 import bleach
46
46
47 from pyramid import compat
47 from pyramid import compat
48 from datetime import datetime
48 from datetime import datetime
49 from functools import partial
49 from functools import partial
50 from pygments.formatters.html import HtmlFormatter
50 from pygments.formatters.html import HtmlFormatter
51 from pygments.lexers import (
51 from pygments.lexers import (
52 get_lexer_by_name, get_lexer_for_filename, get_lexer_for_mimetype)
52 get_lexer_by_name, get_lexer_for_filename, get_lexer_for_mimetype)
53
53
54 from pyramid.threadlocal import get_current_request
54 from pyramid.threadlocal import get_current_request
55
55
56 from webhelpers.html import literal, HTML, escape
56 from webhelpers.html import literal, HTML, escape
57 from webhelpers.html.tools import *
57 from webhelpers.html.tools import *
58 from webhelpers.html.builder import make_tag
58 from webhelpers.html.builder import make_tag
59 from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \
59 from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \
60 end_form, file, form as wh_form, hidden, image, javascript_link, link_to, \
60 end_form, file, form as wh_form, hidden, image, javascript_link, link_to, \
61 link_to_if, link_to_unless, ol, required_legend, select, stylesheet_link, \
61 link_to_if, link_to_unless, ol, required_legend, select, stylesheet_link, \
62 submit, text, password, textarea, title, ul, xml_declaration, radio
62 submit, text, password, textarea, title, ul, xml_declaration, radio
63 from webhelpers.html.tools import auto_link, button_to, highlight, \
63 from webhelpers.html.tools import auto_link, button_to, highlight, \
64 js_obfuscate, mail_to, strip_links, strip_tags, tag_re
64 js_obfuscate, mail_to, strip_links, strip_tags, tag_re
65 from webhelpers.text import chop_at, collapse, convert_accented_entities, \
65 from webhelpers.text import chop_at, collapse, convert_accented_entities, \
66 convert_misc_entities, lchop, plural, rchop, remove_formatting, \
66 convert_misc_entities, lchop, plural, rchop, remove_formatting, \
67 replace_whitespace, urlify, truncate, wrap_paragraphs
67 replace_whitespace, urlify, truncate, wrap_paragraphs
68 from webhelpers.date import time_ago_in_words
68 from webhelpers.date import time_ago_in_words
69 from webhelpers.paginate import Page as _Page
69 from webhelpers.paginate import Page as _Page
70 from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \
70 from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \
71 convert_boolean_attrs, NotGiven, _make_safe_id_component
71 convert_boolean_attrs, NotGiven, _make_safe_id_component
72 from webhelpers2.number import format_byte_size
72 from webhelpers2.number import format_byte_size
73
73
74 from rhodecode.lib.action_parser import action_parser
74 from rhodecode.lib.action_parser import action_parser
75 from rhodecode.lib.ext_json import json
75 from rhodecode.lib.ext_json import json
76 from rhodecode.lib.utils import repo_name_slug, get_custom_lexer
76 from rhodecode.lib.utils import repo_name_slug, get_custom_lexer
77 from rhodecode.lib.utils2 import str2bool, safe_unicode, safe_str, \
77 from rhodecode.lib.utils2 import str2bool, safe_unicode, safe_str, \
78 get_commit_safe, datetime_to_time, time_to_datetime, time_to_utcdatetime, \
78 get_commit_safe, datetime_to_time, time_to_datetime, time_to_utcdatetime, \
79 AttributeDict, safe_int, md5, md5_safe
79 AttributeDict, safe_int, md5, md5_safe
80 from rhodecode.lib.markup_renderer import MarkupRenderer, relative_links
80 from rhodecode.lib.markup_renderer import MarkupRenderer, relative_links
81 from rhodecode.lib.vcs.exceptions import CommitDoesNotExistError
81 from rhodecode.lib.vcs.exceptions import CommitDoesNotExistError
82 from rhodecode.lib.vcs.backends.base import BaseChangeset, EmptyCommit
82 from rhodecode.lib.vcs.backends.base import BaseChangeset, EmptyCommit
83 from rhodecode.lib.index.search_utils import get_matching_line_offsets
83 from rhodecode.lib.index.search_utils import get_matching_line_offsets
84 from rhodecode.config.conf import DATE_FORMAT, DATETIME_FORMAT
84 from rhodecode.config.conf import DATE_FORMAT, DATETIME_FORMAT
85 from rhodecode.model.changeset_status import ChangesetStatusModel
85 from rhodecode.model.changeset_status import ChangesetStatusModel
86 from rhodecode.model.db import Permission, User, Repository
86 from rhodecode.model.db import Permission, User, Repository
87 from rhodecode.model.repo_group import RepoGroupModel
87 from rhodecode.model.repo_group import RepoGroupModel
88 from rhodecode.model.settings import IssueTrackerSettingsModel
88 from rhodecode.model.settings import IssueTrackerSettingsModel
89
89
90
90
91 log = logging.getLogger(__name__)
91 log = logging.getLogger(__name__)
92
92
93
93
94 DEFAULT_USER = User.DEFAULT_USER
94 DEFAULT_USER = User.DEFAULT_USER
95 DEFAULT_USER_EMAIL = User.DEFAULT_USER_EMAIL
95 DEFAULT_USER_EMAIL = User.DEFAULT_USER_EMAIL
96
96
97
97
98 def asset(path, ver=None, **kwargs):
98 def asset(path, ver=None, **kwargs):
99 """
99 """
100 Helper to generate a static asset file path for rhodecode assets
100 Helper to generate a static asset file path for rhodecode assets
101
101
102 eg. h.asset('images/image.png', ver='3923')
102 eg. h.asset('images/image.png', ver='3923')
103
103
104 :param path: path of asset
104 :param path: path of asset
105 :param ver: optional version query param to append as ?ver=
105 :param ver: optional version query param to append as ?ver=
106 """
106 """
107 request = get_current_request()
107 request = get_current_request()
108 query = {}
108 query = {}
109 query.update(kwargs)
109 query.update(kwargs)
110 if ver:
110 if ver:
111 query = {'ver': ver}
111 query = {'ver': ver}
112 return request.static_path(
112 return request.static_path(
113 'rhodecode:public/{}'.format(path), _query=query)
113 'rhodecode:public/{}'.format(path), _query=query)
114
114
115
115
116 default_html_escape_table = {
116 default_html_escape_table = {
117 ord('&'): u'&amp;',
117 ord('&'): u'&amp;',
118 ord('<'): u'&lt;',
118 ord('<'): u'&lt;',
119 ord('>'): u'&gt;',
119 ord('>'): u'&gt;',
120 ord('"'): u'&quot;',
120 ord('"'): u'&quot;',
121 ord("'"): u'&#39;',
121 ord("'"): u'&#39;',
122 }
122 }
123
123
124
124
125 def html_escape(text, html_escape_table=default_html_escape_table):
125 def html_escape(text, html_escape_table=default_html_escape_table):
126 """Produce entities within text."""
126 """Produce entities within text."""
127 return text.translate(html_escape_table)
127 return text.translate(html_escape_table)
128
128
129
129
130 def chop_at_smart(s, sub, inclusive=False, suffix_if_chopped=None):
130 def chop_at_smart(s, sub, inclusive=False, suffix_if_chopped=None):
131 """
131 """
132 Truncate string ``s`` at the first occurrence of ``sub``.
132 Truncate string ``s`` at the first occurrence of ``sub``.
133
133
134 If ``inclusive`` is true, truncate just after ``sub`` rather than at it.
134 If ``inclusive`` is true, truncate just after ``sub`` rather than at it.
135 """
135 """
136 suffix_if_chopped = suffix_if_chopped or ''
136 suffix_if_chopped = suffix_if_chopped or ''
137 pos = s.find(sub)
137 pos = s.find(sub)
138 if pos == -1:
138 if pos == -1:
139 return s
139 return s
140
140
141 if inclusive:
141 if inclusive:
142 pos += len(sub)
142 pos += len(sub)
143
143
144 chopped = s[:pos]
144 chopped = s[:pos]
145 left = s[pos:].strip()
145 left = s[pos:].strip()
146
146
147 if left and suffix_if_chopped:
147 if left and suffix_if_chopped:
148 chopped += suffix_if_chopped
148 chopped += suffix_if_chopped
149
149
150 return chopped
150 return chopped
151
151
152
152
153 def shorter(text, size=20):
153 def shorter(text, size=20):
154 postfix = '...'
154 postfix = '...'
155 if len(text) > size:
155 if len(text) > size:
156 return text[:size - len(postfix)] + postfix
156 return text[:size - len(postfix)] + postfix
157 return text
157 return text
158
158
159
159
160 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
160 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
161 """
161 """
162 Reset button
162 Reset button
163 """
163 """
164 _set_input_attrs(attrs, type, name, value)
164 _set_input_attrs(attrs, type, name, value)
165 _set_id_attr(attrs, id, name)
165 _set_id_attr(attrs, id, name)
166 convert_boolean_attrs(attrs, ["disabled"])
166 convert_boolean_attrs(attrs, ["disabled"])
167 return HTML.input(**attrs)
167 return HTML.input(**attrs)
168
168
169 reset = _reset
169 reset = _reset
170 safeid = _make_safe_id_component
170 safeid = _make_safe_id_component
171
171
172
172
173 def branding(name, length=40):
173 def branding(name, length=40):
174 return truncate(name, length, indicator="")
174 return truncate(name, length, indicator="")
175
175
176
176
177 def FID(raw_id, path):
177 def FID(raw_id, path):
178 """
178 """
179 Creates a unique ID for filenode based on it's hash of path and commit
179 Creates a unique ID for filenode based on it's hash of path and commit
180 it's safe to use in urls
180 it's safe to use in urls
181
181
182 :param raw_id:
182 :param raw_id:
183 :param path:
183 :param path:
184 """
184 """
185
185
186 return 'c-%s-%s' % (short_id(raw_id), md5_safe(path)[:12])
186 return 'c-%s-%s' % (short_id(raw_id), md5_safe(path)[:12])
187
187
188
188
189 class _GetError(object):
189 class _GetError(object):
190 """Get error from form_errors, and represent it as span wrapped error
190 """Get error from form_errors, and represent it as span wrapped error
191 message
191 message
192
192
193 :param field_name: field to fetch errors for
193 :param field_name: field to fetch errors for
194 :param form_errors: form errors dict
194 :param form_errors: form errors dict
195 """
195 """
196
196
197 def __call__(self, field_name, form_errors):
197 def __call__(self, field_name, form_errors):
198 tmpl = """<span class="error_msg">%s</span>"""
198 tmpl = """<span class="error_msg">%s</span>"""
199 if form_errors and field_name in form_errors:
199 if form_errors and field_name in form_errors:
200 return literal(tmpl % form_errors.get(field_name))
200 return literal(tmpl % form_errors.get(field_name))
201
201
202
202 get_error = _GetError()
203 get_error = _GetError()
203
204
204
205
205 class _ToolTip(object):
206 class _ToolTip(object):
206
207
207 def __call__(self, tooltip_title, trim_at=50):
208 def __call__(self, tooltip_title, trim_at=50):
208 """
209 """
209 Special function just to wrap our text into nice formatted
210 Special function just to wrap our text into nice formatted
210 autowrapped text
211 autowrapped text
211
212
212 :param tooltip_title:
213 :param tooltip_title:
213 """
214 """
214 tooltip_title = escape(tooltip_title)
215 tooltip_title = escape(tooltip_title)
215 tooltip_title = tooltip_title.replace('<', '&lt;').replace('>', '&gt;')
216 tooltip_title = tooltip_title.replace('<', '&lt;').replace('>', '&gt;')
216 return tooltip_title
217 return tooltip_title
217
218
219
218 tooltip = _ToolTip()
220 tooltip = _ToolTip()
219
221
220
222
221 def files_breadcrumbs(repo_name, commit_id, file_path, at_ref=None):
223 def files_breadcrumbs(repo_name, commit_id, file_path, at_ref=None, limit_items=False):
222 if isinstance(file_path, str):
224 if isinstance(file_path, str):
223 file_path = safe_unicode(file_path)
225 file_path = safe_unicode(file_path)
226
224 route_qry = {'at': at_ref} if at_ref else None
227 route_qry = {'at': at_ref} if at_ref else None
225
228
226 # TODO: johbo: Is this always a url like path, or is this operating
229 # first segment is a `..` link to repo files
227 # system dependent?
230 root_name = literal(u'<i class="icon-home"></i>')
228 path_segments = file_path.split('/')
231 url_segments = [
232 link_to(
233 root_name,
234 route_path(
235 'repo_files',
236 repo_name=repo_name,
237 commit_id=commit_id,
238 f_path='',
239 _query=route_qry),
240 )]
229
241
230 repo_name_html = escape(repo_name)
242 path_segments = file_path.split('/')
231 if len(path_segments) == 1 and path_segments[0] == '':
232 url_segments = [repo_name_html]
233 else:
234 url_segments = [
235 link_to(
236 repo_name_html,
237 route_path(
238 'repo_files',
239 repo_name=repo_name,
240 commit_id=commit_id,
241 f_path='',
242 _query=route_qry),
243 )]
244
245 last_cnt = len(path_segments) - 1
243 last_cnt = len(path_segments) - 1
246 for cnt, segment in enumerate(path_segments):
244 for cnt, segment in enumerate(path_segments):
247 if not segment:
245 if not segment:
248 continue
246 continue
249 segment_html = escape(segment)
247 segment_html = escape(segment)
250
248
251 if cnt != last_cnt:
249 if cnt != last_cnt:
252 url_segments.append(
250 url_segments.append(
253 link_to(
251 link_to(
254 segment_html,
252 segment_html,
255 route_path(
253 route_path(
256 'repo_files',
254 'repo_files',
257 repo_name=repo_name,
255 repo_name=repo_name,
258 commit_id=commit_id,
256 commit_id=commit_id,
259 f_path='/'.join(path_segments[:cnt + 1]),
257 f_path='/'.join(path_segments[:cnt + 1]),
260 _query=route_qry),
258 _query=route_qry),
261 ))
259 ))
262 else:
260 else:
263 url_segments.append(segment_html)
261 url_segments.append(segment_html)
264
262
265 return literal('/'.join(url_segments))
263 limited_url_segments = url_segments[:1] + ['...'] + url_segments[-5:]
264 if limit_items and len(limited_url_segments) < len(url_segments):
265 url_segments = limited_url_segments
266
267 full_path = file_path
268 icon = '<i class="file-breadcrumb-copy tooltip icon-clipboard clipboard-action" data-clipboard-text="{}" title="Copy the full path"></i>'.format(full_path)
269 if file_path == '':
270 return root_name
271 else:
272 return literal(' / '.join(url_segments) + icon)
266
273
267
274
268 def code_highlight(code, lexer, formatter, use_hl_filter=False):
275 def code_highlight(code, lexer, formatter, use_hl_filter=False):
269 """
276 """
270 Lex ``code`` with ``lexer`` and format it with the formatter ``formatter``.
277 Lex ``code`` with ``lexer`` and format it with the formatter ``formatter``.
271
278
272 If ``outfile`` is given and a valid file object (an object
279 If ``outfile`` is given and a valid file object (an object
273 with a ``write`` method), the result will be written to it, otherwise
280 with a ``write`` method), the result will be written to it, otherwise
274 it is returned as a string.
281 it is returned as a string.
275 """
282 """
276 if use_hl_filter:
283 if use_hl_filter:
277 # add HL filter
284 # add HL filter
278 from rhodecode.lib.index import search_utils
285 from rhodecode.lib.index import search_utils
279 lexer.add_filter(search_utils.ElasticSearchHLFilter())
286 lexer.add_filter(search_utils.ElasticSearchHLFilter())
280 return pygments.format(pygments.lex(code, lexer), formatter)
287 return pygments.format(pygments.lex(code, lexer), formatter)
281
288
282
289
283 class CodeHtmlFormatter(HtmlFormatter):
290 class CodeHtmlFormatter(HtmlFormatter):
284 """
291 """
285 My code Html Formatter for source codes
292 My code Html Formatter for source codes
286 """
293 """
287
294
288 def wrap(self, source, outfile):
295 def wrap(self, source, outfile):
289 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
296 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
290
297
291 def _wrap_code(self, source):
298 def _wrap_code(self, source):
292 for cnt, it in enumerate(source):
299 for cnt, it in enumerate(source):
293 i, t = it
300 i, t = it
294 t = '<div id="L%s">%s</div>' % (cnt + 1, t)
301 t = '<div id="L%s">%s</div>' % (cnt + 1, t)
295 yield i, t
302 yield i, t
296
303
297 def _wrap_tablelinenos(self, inner):
304 def _wrap_tablelinenos(self, inner):
298 dummyoutfile = StringIO.StringIO()
305 dummyoutfile = StringIO.StringIO()
299 lncount = 0
306 lncount = 0
300 for t, line in inner:
307 for t, line in inner:
301 if t:
308 if t:
302 lncount += 1
309 lncount += 1
303 dummyoutfile.write(line)
310 dummyoutfile.write(line)
304
311
305 fl = self.linenostart
312 fl = self.linenostart
306 mw = len(str(lncount + fl - 1))
313 mw = len(str(lncount + fl - 1))
307 sp = self.linenospecial
314 sp = self.linenospecial
308 st = self.linenostep
315 st = self.linenostep
309 la = self.lineanchors
316 la = self.lineanchors
310 aln = self.anchorlinenos
317 aln = self.anchorlinenos
311 nocls = self.noclasses
318 nocls = self.noclasses
312 if sp:
319 if sp:
313 lines = []
320 lines = []
314
321
315 for i in range(fl, fl + lncount):
322 for i in range(fl, fl + lncount):
316 if i % st == 0:
323 if i % st == 0:
317 if i % sp == 0:
324 if i % sp == 0:
318 if aln:
325 if aln:
319 lines.append('<a href="#%s%d" class="special">%*d</a>' %
326 lines.append('<a href="#%s%d" class="special">%*d</a>' %
320 (la, i, mw, i))
327 (la, i, mw, i))
321 else:
328 else:
322 lines.append('<span class="special">%*d</span>' % (mw, i))
329 lines.append('<span class="special">%*d</span>' % (mw, i))
323 else:
330 else:
324 if aln:
331 if aln:
325 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
332 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
326 else:
333 else:
327 lines.append('%*d' % (mw, i))
334 lines.append('%*d' % (mw, i))
328 else:
335 else:
329 lines.append('')
336 lines.append('')
330 ls = '\n'.join(lines)
337 ls = '\n'.join(lines)
331 else:
338 else:
332 lines = []
339 lines = []
333 for i in range(fl, fl + lncount):
340 for i in range(fl, fl + lncount):
334 if i % st == 0:
341 if i % st == 0:
335 if aln:
342 if aln:
336 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
343 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
337 else:
344 else:
338 lines.append('%*d' % (mw, i))
345 lines.append('%*d' % (mw, i))
339 else:
346 else:
340 lines.append('')
347 lines.append('')
341 ls = '\n'.join(lines)
348 ls = '\n'.join(lines)
342
349
343 # in case you wonder about the seemingly redundant <div> here: since the
350 # in case you wonder about the seemingly redundant <div> here: since the
344 # content in the other cell also is wrapped in a div, some browsers in
351 # content in the other cell also is wrapped in a div, some browsers in
345 # some configurations seem to mess up the formatting...
352 # some configurations seem to mess up the formatting...
346 if nocls:
353 if nocls:
347 yield 0, ('<table class="%stable">' % self.cssclass +
354 yield 0, ('<table class="%stable">' % self.cssclass +
348 '<tr><td><div class="linenodiv" '
355 '<tr><td><div class="linenodiv" '
349 'style="background-color: #f0f0f0; padding-right: 10px">'
356 'style="background-color: #f0f0f0; padding-right: 10px">'
350 '<pre style="line-height: 125%">' +
357 '<pre style="line-height: 125%">' +
351 ls + '</pre></div></td><td id="hlcode" class="code">')
358 ls + '</pre></div></td><td id="hlcode" class="code">')
352 else:
359 else:
353 yield 0, ('<table class="%stable">' % self.cssclass +
360 yield 0, ('<table class="%stable">' % self.cssclass +
354 '<tr><td class="linenos"><div class="linenodiv"><pre>' +
361 '<tr><td class="linenos"><div class="linenodiv"><pre>' +
355 ls + '</pre></div></td><td id="hlcode" class="code">')
362 ls + '</pre></div></td><td id="hlcode" class="code">')
356 yield 0, dummyoutfile.getvalue()
363 yield 0, dummyoutfile.getvalue()
357 yield 0, '</td></tr></table>'
364 yield 0, '</td></tr></table>'
358
365
359
366
360 class SearchContentCodeHtmlFormatter(CodeHtmlFormatter):
367 class SearchContentCodeHtmlFormatter(CodeHtmlFormatter):
361 def __init__(self, **kw):
368 def __init__(self, **kw):
362 # only show these line numbers if set
369 # only show these line numbers if set
363 self.only_lines = kw.pop('only_line_numbers', [])
370 self.only_lines = kw.pop('only_line_numbers', [])
364 self.query_terms = kw.pop('query_terms', [])
371 self.query_terms = kw.pop('query_terms', [])
365 self.max_lines = kw.pop('max_lines', 5)
372 self.max_lines = kw.pop('max_lines', 5)
366 self.line_context = kw.pop('line_context', 3)
373 self.line_context = kw.pop('line_context', 3)
367 self.url = kw.pop('url', None)
374 self.url = kw.pop('url', None)
368
375
369 super(CodeHtmlFormatter, self).__init__(**kw)
376 super(CodeHtmlFormatter, self).__init__(**kw)
370
377
371 def _wrap_code(self, source):
378 def _wrap_code(self, source):
372 for cnt, it in enumerate(source):
379 for cnt, it in enumerate(source):
373 i, t = it
380 i, t = it
374 t = '<pre>%s</pre>' % t
381 t = '<pre>%s</pre>' % t
375 yield i, t
382 yield i, t
376
383
377 def _wrap_tablelinenos(self, inner):
384 def _wrap_tablelinenos(self, inner):
378 yield 0, '<table class="code-highlight %stable">' % self.cssclass
385 yield 0, '<table class="code-highlight %stable">' % self.cssclass
379
386
380 last_shown_line_number = 0
387 last_shown_line_number = 0
381 current_line_number = 1
388 current_line_number = 1
382
389
383 for t, line in inner:
390 for t, line in inner:
384 if not t:
391 if not t:
385 yield t, line
392 yield t, line
386 continue
393 continue
387
394
388 if current_line_number in self.only_lines:
395 if current_line_number in self.only_lines:
389 if last_shown_line_number + 1 != current_line_number:
396 if last_shown_line_number + 1 != current_line_number:
390 yield 0, '<tr>'
397 yield 0, '<tr>'
391 yield 0, '<td class="line">...</td>'
398 yield 0, '<td class="line">...</td>'
392 yield 0, '<td id="hlcode" class="code"></td>'
399 yield 0, '<td id="hlcode" class="code"></td>'
393 yield 0, '</tr>'
400 yield 0, '</tr>'
394
401
395 yield 0, '<tr>'
402 yield 0, '<tr>'
396 if self.url:
403 if self.url:
397 yield 0, '<td class="line"><a href="%s#L%i">%i</a></td>' % (
404 yield 0, '<td class="line"><a href="%s#L%i">%i</a></td>' % (
398 self.url, current_line_number, current_line_number)
405 self.url, current_line_number, current_line_number)
399 else:
406 else:
400 yield 0, '<td class="line"><a href="">%i</a></td>' % (
407 yield 0, '<td class="line"><a href="">%i</a></td>' % (
401 current_line_number)
408 current_line_number)
402 yield 0, '<td id="hlcode" class="code">' + line + '</td>'
409 yield 0, '<td id="hlcode" class="code">' + line + '</td>'
403 yield 0, '</tr>'
410 yield 0, '</tr>'
404
411
405 last_shown_line_number = current_line_number
412 last_shown_line_number = current_line_number
406
413
407 current_line_number += 1
414 current_line_number += 1
408
415
409 yield 0, '</table>'
416 yield 0, '</table>'
410
417
411
418
412 def hsv_to_rgb(h, s, v):
419 def hsv_to_rgb(h, s, v):
413 """ Convert hsv color values to rgb """
420 """ Convert hsv color values to rgb """
414
421
415 if s == 0.0:
422 if s == 0.0:
416 return v, v, v
423 return v, v, v
417 i = int(h * 6.0) # XXX assume int() truncates!
424 i = int(h * 6.0) # XXX assume int() truncates!
418 f = (h * 6.0) - i
425 f = (h * 6.0) - i
419 p = v * (1.0 - s)
426 p = v * (1.0 - s)
420 q = v * (1.0 - s * f)
427 q = v * (1.0 - s * f)
421 t = v * (1.0 - s * (1.0 - f))
428 t = v * (1.0 - s * (1.0 - f))
422 i = i % 6
429 i = i % 6
423 if i == 0:
430 if i == 0:
424 return v, t, p
431 return v, t, p
425 if i == 1:
432 if i == 1:
426 return q, v, p
433 return q, v, p
427 if i == 2:
434 if i == 2:
428 return p, v, t
435 return p, v, t
429 if i == 3:
436 if i == 3:
430 return p, q, v
437 return p, q, v
431 if i == 4:
438 if i == 4:
432 return t, p, v
439 return t, p, v
433 if i == 5:
440 if i == 5:
434 return v, p, q
441 return v, p, q
435
442
436
443
437 def unique_color_generator(n=10000, saturation=0.10, lightness=0.95):
444 def unique_color_generator(n=10000, saturation=0.10, lightness=0.95):
438 """
445 """
439 Generator for getting n of evenly distributed colors using
446 Generator for getting n of evenly distributed colors using
440 hsv color and golden ratio. It always return same order of colors
447 hsv color and golden ratio. It always return same order of colors
441
448
442 :param n: number of colors to generate
449 :param n: number of colors to generate
443 :param saturation: saturation of returned colors
450 :param saturation: saturation of returned colors
444 :param lightness: lightness of returned colors
451 :param lightness: lightness of returned colors
445 :returns: RGB tuple
452 :returns: RGB tuple
446 """
453 """
447
454
448 golden_ratio = 0.618033988749895
455 golden_ratio = 0.618033988749895
449 h = 0.22717784590367374
456 h = 0.22717784590367374
450
457
451 for _ in xrange(n):
458 for _ in xrange(n):
452 h += golden_ratio
459 h += golden_ratio
453 h %= 1
460 h %= 1
454 HSV_tuple = [h, saturation, lightness]
461 HSV_tuple = [h, saturation, lightness]
455 RGB_tuple = hsv_to_rgb(*HSV_tuple)
462 RGB_tuple = hsv_to_rgb(*HSV_tuple)
456 yield map(lambda x: str(int(x * 256)), RGB_tuple)
463 yield map(lambda x: str(int(x * 256)), RGB_tuple)
457
464
458
465
459 def color_hasher(n=10000, saturation=0.10, lightness=0.95):
466 def color_hasher(n=10000, saturation=0.10, lightness=0.95):
460 """
467 """
461 Returns a function which when called with an argument returns a unique
468 Returns a function which when called with an argument returns a unique
462 color for that argument, eg.
469 color for that argument, eg.
463
470
464 :param n: number of colors to generate
471 :param n: number of colors to generate
465 :param saturation: saturation of returned colors
472 :param saturation: saturation of returned colors
466 :param lightness: lightness of returned colors
473 :param lightness: lightness of returned colors
467 :returns: css RGB string
474 :returns: css RGB string
468
475
469 >>> color_hash = color_hasher()
476 >>> color_hash = color_hasher()
470 >>> color_hash('hello')
477 >>> color_hash('hello')
471 'rgb(34, 12, 59)'
478 'rgb(34, 12, 59)'
472 >>> color_hash('hello')
479 >>> color_hash('hello')
473 'rgb(34, 12, 59)'
480 'rgb(34, 12, 59)'
474 >>> color_hash('other')
481 >>> color_hash('other')
475 'rgb(90, 224, 159)'
482 'rgb(90, 224, 159)'
476 """
483 """
477
484
478 color_dict = {}
485 color_dict = {}
479 cgenerator = unique_color_generator(
486 cgenerator = unique_color_generator(
480 saturation=saturation, lightness=lightness)
487 saturation=saturation, lightness=lightness)
481
488
482 def get_color_string(thing):
489 def get_color_string(thing):
483 if thing in color_dict:
490 if thing in color_dict:
484 col = color_dict[thing]
491 col = color_dict[thing]
485 else:
492 else:
486 col = color_dict[thing] = cgenerator.next()
493 col = color_dict[thing] = cgenerator.next()
487 return "rgb(%s)" % (', '.join(col))
494 return "rgb(%s)" % (', '.join(col))
488
495
489 return get_color_string
496 return get_color_string
490
497
491
498
492 def get_lexer_safe(mimetype=None, filepath=None):
499 def get_lexer_safe(mimetype=None, filepath=None):
493 """
500 """
494 Tries to return a relevant pygments lexer using mimetype/filepath name,
501 Tries to return a relevant pygments lexer using mimetype/filepath name,
495 defaulting to plain text if none could be found
502 defaulting to plain text if none could be found
496 """
503 """
497 lexer = None
504 lexer = None
498 try:
505 try:
499 if mimetype:
506 if mimetype:
500 lexer = get_lexer_for_mimetype(mimetype)
507 lexer = get_lexer_for_mimetype(mimetype)
501 if not lexer:
508 if not lexer:
502 lexer = get_lexer_for_filename(filepath)
509 lexer = get_lexer_for_filename(filepath)
503 except pygments.util.ClassNotFound:
510 except pygments.util.ClassNotFound:
504 pass
511 pass
505
512
506 if not lexer:
513 if not lexer:
507 lexer = get_lexer_by_name('text')
514 lexer = get_lexer_by_name('text')
508
515
509 return lexer
516 return lexer
510
517
511
518
512 def get_lexer_for_filenode(filenode):
519 def get_lexer_for_filenode(filenode):
513 lexer = get_custom_lexer(filenode.extension) or filenode.lexer
520 lexer = get_custom_lexer(filenode.extension) or filenode.lexer
514 return lexer
521 return lexer
515
522
516
523
517 def pygmentize(filenode, **kwargs):
524 def pygmentize(filenode, **kwargs):
518 """
525 """
519 pygmentize function using pygments
526 pygmentize function using pygments
520
527
521 :param filenode:
528 :param filenode:
522 """
529 """
523 lexer = get_lexer_for_filenode(filenode)
530 lexer = get_lexer_for_filenode(filenode)
524 return literal(code_highlight(filenode.content, lexer,
531 return literal(code_highlight(filenode.content, lexer,
525 CodeHtmlFormatter(**kwargs)))
532 CodeHtmlFormatter(**kwargs)))
526
533
527
534
528 def is_following_repo(repo_name, user_id):
535 def is_following_repo(repo_name, user_id):
529 from rhodecode.model.scm import ScmModel
536 from rhodecode.model.scm import ScmModel
530 return ScmModel().is_following_repo(repo_name, user_id)
537 return ScmModel().is_following_repo(repo_name, user_id)
531
538
532
539
533 class _Message(object):
540 class _Message(object):
534 """A message returned by ``Flash.pop_messages()``.
541 """A message returned by ``Flash.pop_messages()``.
535
542
536 Converting the message to a string returns the message text. Instances
543 Converting the message to a string returns the message text. Instances
537 also have the following attributes:
544 also have the following attributes:
538
545
539 * ``message``: the message text.
546 * ``message``: the message text.
540 * ``category``: the category specified when the message was created.
547 * ``category``: the category specified when the message was created.
541 """
548 """
542
549
543 def __init__(self, category, message):
550 def __init__(self, category, message):
544 self.category = category
551 self.category = category
545 self.message = message
552 self.message = message
546
553
547 def __str__(self):
554 def __str__(self):
548 return self.message
555 return self.message
549
556
550 __unicode__ = __str__
557 __unicode__ = __str__
551
558
552 def __html__(self):
559 def __html__(self):
553 return escape(safe_unicode(self.message))
560 return escape(safe_unicode(self.message))
554
561
555
562
556 class Flash(object):
563 class Flash(object):
557 # List of allowed categories. If None, allow any category.
564 # List of allowed categories. If None, allow any category.
558 categories = ["warning", "notice", "error", "success"]
565 categories = ["warning", "notice", "error", "success"]
559
566
560 # Default category if none is specified.
567 # Default category if none is specified.
561 default_category = "notice"
568 default_category = "notice"
562
569
563 def __init__(self, session_key="flash", categories=None,
570 def __init__(self, session_key="flash", categories=None,
564 default_category=None):
571 default_category=None):
565 """
572 """
566 Instantiate a ``Flash`` object.
573 Instantiate a ``Flash`` object.
567
574
568 ``session_key`` is the key to save the messages under in the user's
575 ``session_key`` is the key to save the messages under in the user's
569 session.
576 session.
570
577
571 ``categories`` is an optional list which overrides the default list
578 ``categories`` is an optional list which overrides the default list
572 of categories.
579 of categories.
573
580
574 ``default_category`` overrides the default category used for messages
581 ``default_category`` overrides the default category used for messages
575 when none is specified.
582 when none is specified.
576 """
583 """
577 self.session_key = session_key
584 self.session_key = session_key
578 if categories is not None:
585 if categories is not None:
579 self.categories = categories
586 self.categories = categories
580 if default_category is not None:
587 if default_category is not None:
581 self.default_category = default_category
588 self.default_category = default_category
582 if self.categories and self.default_category not in self.categories:
589 if self.categories and self.default_category not in self.categories:
583 raise ValueError(
590 raise ValueError(
584 "unrecognized default category %r" % (self.default_category,))
591 "unrecognized default category %r" % (self.default_category,))
585
592
586 def pop_messages(self, session=None, request=None):
593 def pop_messages(self, session=None, request=None):
587 """
594 """
588 Return all accumulated messages and delete them from the session.
595 Return all accumulated messages and delete them from the session.
589
596
590 The return value is a list of ``Message`` objects.
597 The return value is a list of ``Message`` objects.
591 """
598 """
592 messages = []
599 messages = []
593
600
594 if not session:
601 if not session:
595 if not request:
602 if not request:
596 request = get_current_request()
603 request = get_current_request()
597 session = request.session
604 session = request.session
598
605
599 # Pop the 'old' pylons flash messages. They are tuples of the form
606 # Pop the 'old' pylons flash messages. They are tuples of the form
600 # (category, message)
607 # (category, message)
601 for cat, msg in session.pop(self.session_key, []):
608 for cat, msg in session.pop(self.session_key, []):
602 messages.append(_Message(cat, msg))
609 messages.append(_Message(cat, msg))
603
610
604 # Pop the 'new' pyramid flash messages for each category as list
611 # Pop the 'new' pyramid flash messages for each category as list
605 # of strings.
612 # of strings.
606 for cat in self.categories:
613 for cat in self.categories:
607 for msg in session.pop_flash(queue=cat):
614 for msg in session.pop_flash(queue=cat):
608 messages.append(_Message(cat, msg))
615 messages.append(_Message(cat, msg))
609 # Map messages from the default queue to the 'notice' category.
616 # Map messages from the default queue to the 'notice' category.
610 for msg in session.pop_flash():
617 for msg in session.pop_flash():
611 messages.append(_Message('notice', msg))
618 messages.append(_Message('notice', msg))
612
619
613 session.save()
620 session.save()
614 return messages
621 return messages
615
622
616 def json_alerts(self, session=None, request=None):
623 def json_alerts(self, session=None, request=None):
617 payloads = []
624 payloads = []
618 messages = flash.pop_messages(session=session, request=request)
625 messages = flash.pop_messages(session=session, request=request)
619 if messages:
626 if messages:
620 for message in messages:
627 for message in messages:
621 subdata = {}
628 subdata = {}
622 if hasattr(message.message, 'rsplit'):
629 if hasattr(message.message, 'rsplit'):
623 flash_data = message.message.rsplit('|DELIM|', 1)
630 flash_data = message.message.rsplit('|DELIM|', 1)
624 org_message = flash_data[0]
631 org_message = flash_data[0]
625 if len(flash_data) > 1:
632 if len(flash_data) > 1:
626 subdata = json.loads(flash_data[1])
633 subdata = json.loads(flash_data[1])
627 else:
634 else:
628 org_message = message.message
635 org_message = message.message
629 payloads.append({
636 payloads.append({
630 'message': {
637 'message': {
631 'message': u'{}'.format(org_message),
638 'message': u'{}'.format(org_message),
632 'level': message.category,
639 'level': message.category,
633 'force': True,
640 'force': True,
634 'subdata': subdata
641 'subdata': subdata
635 }
642 }
636 })
643 })
637 return json.dumps(payloads)
644 return json.dumps(payloads)
638
645
639 def __call__(self, message, category=None, ignore_duplicate=False,
646 def __call__(self, message, category=None, ignore_duplicate=False,
640 session=None, request=None):
647 session=None, request=None):
641
648
642 if not session:
649 if not session:
643 if not request:
650 if not request:
644 request = get_current_request()
651 request = get_current_request()
645 session = request.session
652 session = request.session
646
653
647 session.flash(
654 session.flash(
648 message, queue=category, allow_duplicate=not ignore_duplicate)
655 message, queue=category, allow_duplicate=not ignore_duplicate)
649
656
650
657
651 flash = Flash()
658 flash = Flash()
652
659
653 #==============================================================================
660 #==============================================================================
654 # SCM FILTERS available via h.
661 # SCM FILTERS available via h.
655 #==============================================================================
662 #==============================================================================
656 from rhodecode.lib.vcs.utils import author_name, author_email
663 from rhodecode.lib.vcs.utils import author_name, author_email
657 from rhodecode.lib.utils2 import credentials_filter, age, age_from_seconds
664 from rhodecode.lib.utils2 import credentials_filter, age, age_from_seconds
658 from rhodecode.model.db import User, ChangesetStatus
665 from rhodecode.model.db import User, ChangesetStatus
659
666
660 capitalize = lambda x: x.capitalize()
667 capitalize = lambda x: x.capitalize()
661 email = author_email
668 email = author_email
662 short_id = lambda x: x[:12]
669 short_id = lambda x: x[:12]
663 hide_credentials = lambda x: ''.join(credentials_filter(x))
670 hide_credentials = lambda x: ''.join(credentials_filter(x))
664
671
665
672
666 import pytz
673 import pytz
667 import tzlocal
674 import tzlocal
668 local_timezone = tzlocal.get_localzone()
675 local_timezone = tzlocal.get_localzone()
669
676
670
677
671 def age_component(datetime_iso, value=None, time_is_local=False):
678 def age_component(datetime_iso, value=None, time_is_local=False):
672 title = value or format_date(datetime_iso)
679 title = value or format_date(datetime_iso)
673 tzinfo = '+00:00'
680 tzinfo = '+00:00'
674
681
675 # detect if we have a timezone info, otherwise, add it
682 # detect if we have a timezone info, otherwise, add it
676 if time_is_local and isinstance(datetime_iso, datetime) and not datetime_iso.tzinfo:
683 if time_is_local and isinstance(datetime_iso, datetime) and not datetime_iso.tzinfo:
677 force_timezone = os.environ.get('RC_TIMEZONE', '')
684 force_timezone = os.environ.get('RC_TIMEZONE', '')
678 if force_timezone:
685 if force_timezone:
679 force_timezone = pytz.timezone(force_timezone)
686 force_timezone = pytz.timezone(force_timezone)
680 timezone = force_timezone or local_timezone
687 timezone = force_timezone or local_timezone
681 offset = timezone.localize(datetime_iso).strftime('%z')
688 offset = timezone.localize(datetime_iso).strftime('%z')
682 tzinfo = '{}:{}'.format(offset[:-2], offset[-2:])
689 tzinfo = '{}:{}'.format(offset[:-2], offset[-2:])
683
690
684 return literal(
691 return literal(
685 '<time class="timeago tooltip" '
692 '<time class="timeago tooltip" '
686 'title="{1}{2}" datetime="{0}{2}">{1}</time>'.format(
693 'title="{1}{2}" datetime="{0}{2}">{1}</time>'.format(
687 datetime_iso, title, tzinfo))
694 datetime_iso, title, tzinfo))
688
695
689
696
690 def _shorten_commit_id(commit_id, commit_len=None):
697 def _shorten_commit_id(commit_id, commit_len=None):
691 if commit_len is None:
698 if commit_len is None:
692 request = get_current_request()
699 request = get_current_request()
693 commit_len = request.call_context.visual.show_sha_length
700 commit_len = request.call_context.visual.show_sha_length
694 return commit_id[:commit_len]
701 return commit_id[:commit_len]
695
702
696
703
697 def show_id(commit, show_idx=None, commit_len=None):
704 def show_id(commit, show_idx=None, commit_len=None):
698 """
705 """
699 Configurable function that shows ID
706 Configurable function that shows ID
700 by default it's r123:fffeeefffeee
707 by default it's r123:fffeeefffeee
701
708
702 :param commit: commit instance
709 :param commit: commit instance
703 """
710 """
704 if show_idx is None:
711 if show_idx is None:
705 request = get_current_request()
712 request = get_current_request()
706 show_idx = request.call_context.visual.show_revision_number
713 show_idx = request.call_context.visual.show_revision_number
707
714
708 raw_id = _shorten_commit_id(commit.raw_id, commit_len=commit_len)
715 raw_id = _shorten_commit_id(commit.raw_id, commit_len=commit_len)
709 if show_idx:
716 if show_idx:
710 return 'r%s:%s' % (commit.idx, raw_id)
717 return 'r%s:%s' % (commit.idx, raw_id)
711 else:
718 else:
712 return '%s' % (raw_id, )
719 return '%s' % (raw_id, )
713
720
714
721
715 def format_date(date):
722 def format_date(date):
716 """
723 """
717 use a standardized formatting for dates used in RhodeCode
724 use a standardized formatting for dates used in RhodeCode
718
725
719 :param date: date/datetime object
726 :param date: date/datetime object
720 :return: formatted date
727 :return: formatted date
721 """
728 """
722
729
723 if date:
730 if date:
724 _fmt = "%a, %d %b %Y %H:%M:%S"
731 _fmt = "%a, %d %b %Y %H:%M:%S"
725 return safe_unicode(date.strftime(_fmt))
732 return safe_unicode(date.strftime(_fmt))
726
733
727 return u""
734 return u""
728
735
729
736
730 class _RepoChecker(object):
737 class _RepoChecker(object):
731
738
732 def __init__(self, backend_alias):
739 def __init__(self, backend_alias):
733 self._backend_alias = backend_alias
740 self._backend_alias = backend_alias
734
741
735 def __call__(self, repository):
742 def __call__(self, repository):
736 if hasattr(repository, 'alias'):
743 if hasattr(repository, 'alias'):
737 _type = repository.alias
744 _type = repository.alias
738 elif hasattr(repository, 'repo_type'):
745 elif hasattr(repository, 'repo_type'):
739 _type = repository.repo_type
746 _type = repository.repo_type
740 else:
747 else:
741 _type = repository
748 _type = repository
742 return _type == self._backend_alias
749 return _type == self._backend_alias
743
750
744
751
745 is_git = _RepoChecker('git')
752 is_git = _RepoChecker('git')
746 is_hg = _RepoChecker('hg')
753 is_hg = _RepoChecker('hg')
747 is_svn = _RepoChecker('svn')
754 is_svn = _RepoChecker('svn')
748
755
749
756
750 def get_repo_type_by_name(repo_name):
757 def get_repo_type_by_name(repo_name):
751 repo = Repository.get_by_repo_name(repo_name)
758 repo = Repository.get_by_repo_name(repo_name)
752 if repo:
759 if repo:
753 return repo.repo_type
760 return repo.repo_type
754
761
755
762
756 def is_svn_without_proxy(repository):
763 def is_svn_without_proxy(repository):
757 if is_svn(repository):
764 if is_svn(repository):
758 from rhodecode.model.settings import VcsSettingsModel
765 from rhodecode.model.settings import VcsSettingsModel
759 conf = VcsSettingsModel().get_ui_settings_as_config_obj()
766 conf = VcsSettingsModel().get_ui_settings_as_config_obj()
760 return not str2bool(conf.get('vcs_svn_proxy', 'http_requests_enabled'))
767 return not str2bool(conf.get('vcs_svn_proxy', 'http_requests_enabled'))
761 return False
768 return False
762
769
763
770
764 def discover_user(author):
771 def discover_user(author):
765 """
772 """
766 Tries to discover RhodeCode User based on the autho string. Author string
773 Tries to discover RhodeCode User based on the autho string. Author string
767 is typically `FirstName LastName <email@address.com>`
774 is typically `FirstName LastName <email@address.com>`
768 """
775 """
769
776
770 # if author is already an instance use it for extraction
777 # if author is already an instance use it for extraction
771 if isinstance(author, User):
778 if isinstance(author, User):
772 return author
779 return author
773
780
774 # Valid email in the attribute passed, see if they're in the system
781 # Valid email in the attribute passed, see if they're in the system
775 _email = author_email(author)
782 _email = author_email(author)
776 if _email != '':
783 if _email != '':
777 user = User.get_by_email(_email, case_insensitive=True, cache=True)
784 user = User.get_by_email(_email, case_insensitive=True, cache=True)
778 if user is not None:
785 if user is not None:
779 return user
786 return user
780
787
781 # Maybe it's a username, we try to extract it and fetch by username ?
788 # Maybe it's a username, we try to extract it and fetch by username ?
782 _author = author_name(author)
789 _author = author_name(author)
783 user = User.get_by_username(_author, case_insensitive=True, cache=True)
790 user = User.get_by_username(_author, case_insensitive=True, cache=True)
784 if user is not None:
791 if user is not None:
785 return user
792 return user
786
793
787 return None
794 return None
788
795
789
796
790 def email_or_none(author):
797 def email_or_none(author):
791 # extract email from the commit string
798 # extract email from the commit string
792 _email = author_email(author)
799 _email = author_email(author)
793
800
794 # If we have an email, use it, otherwise
801 # If we have an email, use it, otherwise
795 # see if it contains a username we can get an email from
802 # see if it contains a username we can get an email from
796 if _email != '':
803 if _email != '':
797 return _email
804 return _email
798 else:
805 else:
799 user = User.get_by_username(
806 user = User.get_by_username(
800 author_name(author), case_insensitive=True, cache=True)
807 author_name(author), case_insensitive=True, cache=True)
801
808
802 if user is not None:
809 if user is not None:
803 return user.email
810 return user.email
804
811
805 # No valid email, not a valid user in the system, none!
812 # No valid email, not a valid user in the system, none!
806 return None
813 return None
807
814
808
815
809 def link_to_user(author, length=0, **kwargs):
816 def link_to_user(author, length=0, **kwargs):
810 user = discover_user(author)
817 user = discover_user(author)
811 # user can be None, but if we have it already it means we can re-use it
818 # user can be None, but if we have it already it means we can re-use it
812 # in the person() function, so we save 1 intensive-query
819 # in the person() function, so we save 1 intensive-query
813 if user:
820 if user:
814 author = user
821 author = user
815
822
816 display_person = person(author, 'username_or_name_or_email')
823 display_person = person(author, 'username_or_name_or_email')
817 if length:
824 if length:
818 display_person = shorter(display_person, length)
825 display_person = shorter(display_person, length)
819
826
820 if user:
827 if user:
821 return link_to(
828 return link_to(
822 escape(display_person),
829 escape(display_person),
823 route_path('user_profile', username=user.username),
830 route_path('user_profile', username=user.username),
824 **kwargs)
831 **kwargs)
825 else:
832 else:
826 return escape(display_person)
833 return escape(display_person)
827
834
828
835
829 def link_to_group(users_group_name, **kwargs):
836 def link_to_group(users_group_name, **kwargs):
830 return link_to(
837 return link_to(
831 escape(users_group_name),
838 escape(users_group_name),
832 route_path('user_group_profile', user_group_name=users_group_name),
839 route_path('user_group_profile', user_group_name=users_group_name),
833 **kwargs)
840 **kwargs)
834
841
835
842
836 def person(author, show_attr="username_and_name"):
843 def person(author, show_attr="username_and_name"):
837 user = discover_user(author)
844 user = discover_user(author)
838 if user:
845 if user:
839 return getattr(user, show_attr)
846 return getattr(user, show_attr)
840 else:
847 else:
841 _author = author_name(author)
848 _author = author_name(author)
842 _email = email(author)
849 _email = email(author)
843 return _author or _email
850 return _author or _email
844
851
845
852
846 def author_string(email):
853 def author_string(email):
847 if email:
854 if email:
848 user = User.get_by_email(email, case_insensitive=True, cache=True)
855 user = User.get_by_email(email, case_insensitive=True, cache=True)
849 if user:
856 if user:
850 if user.first_name or user.last_name:
857 if user.first_name or user.last_name:
851 return '%s %s &lt;%s&gt;' % (
858 return '%s %s &lt;%s&gt;' % (
852 user.first_name, user.last_name, email)
859 user.first_name, user.last_name, email)
853 else:
860 else:
854 return email
861 return email
855 else:
862 else:
856 return email
863 return email
857 else:
864 else:
858 return None
865 return None
859
866
860
867
861 def person_by_id(id_, show_attr="username_and_name"):
868 def person_by_id(id_, show_attr="username_and_name"):
862 # attr to return from fetched user
869 # attr to return from fetched user
863 person_getter = lambda usr: getattr(usr, show_attr)
870 person_getter = lambda usr: getattr(usr, show_attr)
864
871
865 #maybe it's an ID ?
872 #maybe it's an ID ?
866 if str(id_).isdigit() or isinstance(id_, int):
873 if str(id_).isdigit() or isinstance(id_, int):
867 id_ = int(id_)
874 id_ = int(id_)
868 user = User.get(id_)
875 user = User.get(id_)
869 if user is not None:
876 if user is not None:
870 return person_getter(user)
877 return person_getter(user)
871 return id_
878 return id_
872
879
873
880
874 def gravatar_with_user(request, author, show_disabled=False):
881 def gravatar_with_user(request, author, show_disabled=False):
875 _render = request.get_partial_renderer(
882 _render = request.get_partial_renderer(
876 'rhodecode:templates/base/base.mako')
883 'rhodecode:templates/base/base.mako')
877 return _render('gravatar_with_user', author, show_disabled=show_disabled)
884 return _render('gravatar_with_user', author, show_disabled=show_disabled)
878
885
879
886
880 tags_paterns = OrderedDict((
887 tags_paterns = OrderedDict((
881 ('lang', (re.compile(r'\[(lang|language)\ \=\&gt;\ *([a-zA-Z\-\/\#\+\.]*)\]'),
888 ('lang', (re.compile(r'\[(lang|language)\ \=\&gt;\ *([a-zA-Z\-\/\#\+\.]*)\]'),
882 '<div class="metatag" tag="lang">\\2</div>')),
889 '<div class="metatag" tag="lang">\\2</div>')),
883
890
884 ('see', (re.compile(r'\[see\ \=\&gt;\ *([a-zA-Z0-9\/\=\?\&amp;\ \:\/\.\-]*)\]'),
891 ('see', (re.compile(r'\[see\ \=\&gt;\ *([a-zA-Z0-9\/\=\?\&amp;\ \:\/\.\-]*)\]'),
885 '<div class="metatag" tag="see">see: \\1 </div>')),
892 '<div class="metatag" tag="see">see: \\1 </div>')),
886
893
887 ('url', (re.compile(r'\[url\ \=\&gt;\ \[([a-zA-Z0-9\ \.\-\_]+)\]\((http://|https://|/)(.*?)\)\]'),
894 ('url', (re.compile(r'\[url\ \=\&gt;\ \[([a-zA-Z0-9\ \.\-\_]+)\]\((http://|https://|/)(.*?)\)\]'),
888 '<div class="metatag" tag="url"> <a href="\\2\\3">\\1</a> </div>')),
895 '<div class="metatag" tag="url"> <a href="\\2\\3">\\1</a> </div>')),
889
896
890 ('license', (re.compile(r'\[license\ \=\&gt;\ *([a-zA-Z0-9\/\=\?\&amp;\ \:\/\.\-]*)\]'),
897 ('license', (re.compile(r'\[license\ \=\&gt;\ *([a-zA-Z0-9\/\=\?\&amp;\ \:\/\.\-]*)\]'),
891 '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/\\1">\\1</a></div>')),
898 '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/\\1">\\1</a></div>')),
892
899
893 ('ref', (re.compile(r'\[(requires|recommends|conflicts|base)\ \=\&gt;\ *([a-zA-Z0-9\-\/]*)\]'),
900 ('ref', (re.compile(r'\[(requires|recommends|conflicts|base)\ \=\&gt;\ *([a-zA-Z0-9\-\/]*)\]'),
894 '<div class="metatag" tag="ref \\1">\\1: <a href="/\\2">\\2</a></div>')),
901 '<div class="metatag" tag="ref \\1">\\1: <a href="/\\2">\\2</a></div>')),
895
902
896 ('state', (re.compile(r'\[(stable|featured|stale|dead|dev|deprecated)\]'),
903 ('state', (re.compile(r'\[(stable|featured|stale|dead|dev|deprecated)\]'),
897 '<div class="metatag" tag="state \\1">\\1</div>')),
904 '<div class="metatag" tag="state \\1">\\1</div>')),
898
905
899 # label in grey
906 # label in grey
900 ('label', (re.compile(r'\[([a-z]+)\]'),
907 ('label', (re.compile(r'\[([a-z]+)\]'),
901 '<div class="metatag" tag="label">\\1</div>')),
908 '<div class="metatag" tag="label">\\1</div>')),
902
909
903 # generic catch all in grey
910 # generic catch all in grey
904 ('generic', (re.compile(r'\[([a-zA-Z0-9\.\-\_]+)\]'),
911 ('generic', (re.compile(r'\[([a-zA-Z0-9\.\-\_]+)\]'),
905 '<div class="metatag" tag="generic">\\1</div>')),
912 '<div class="metatag" tag="generic">\\1</div>')),
906 ))
913 ))
907
914
908
915
909 def extract_metatags(value):
916 def extract_metatags(value):
910 """
917 """
911 Extract supported meta-tags from given text value
918 Extract supported meta-tags from given text value
912 """
919 """
913 tags = []
920 tags = []
914 if not value:
921 if not value:
915 return tags, ''
922 return tags, ''
916
923
917 for key, val in tags_paterns.items():
924 for key, val in tags_paterns.items():
918 pat, replace_html = val
925 pat, replace_html = val
919 tags.extend([(key, x.group()) for x in pat.finditer(value)])
926 tags.extend([(key, x.group()) for x in pat.finditer(value)])
920 value = pat.sub('', value)
927 value = pat.sub('', value)
921
928
922 return tags, value
929 return tags, value
923
930
924
931
925 def style_metatag(tag_type, value):
932 def style_metatag(tag_type, value):
926 """
933 """
927 converts tags from value into html equivalent
934 converts tags from value into html equivalent
928 """
935 """
929 if not value:
936 if not value:
930 return ''
937 return ''
931
938
932 html_value = value
939 html_value = value
933 tag_data = tags_paterns.get(tag_type)
940 tag_data = tags_paterns.get(tag_type)
934 if tag_data:
941 if tag_data:
935 pat, replace_html = tag_data
942 pat, replace_html = tag_data
936 # convert to plain `unicode` instead of a markup tag to be used in
943 # convert to plain `unicode` instead of a markup tag to be used in
937 # regex expressions. safe_unicode doesn't work here
944 # regex expressions. safe_unicode doesn't work here
938 html_value = pat.sub(replace_html, unicode(value))
945 html_value = pat.sub(replace_html, unicode(value))
939
946
940 return html_value
947 return html_value
941
948
942
949
943 def bool2icon(value, show_at_false=True):
950 def bool2icon(value, show_at_false=True):
944 """
951 """
945 Returns boolean value of a given value, represented as html element with
952 Returns boolean value of a given value, represented as html element with
946 classes that will represent icons
953 classes that will represent icons
947
954
948 :param value: given value to convert to html node
955 :param value: given value to convert to html node
949 """
956 """
950
957
951 if value: # does bool conversion
958 if value: # does bool conversion
952 return HTML.tag('i', class_="icon-true")
959 return HTML.tag('i', class_="icon-true")
953 else: # not true as bool
960 else: # not true as bool
954 if show_at_false:
961 if show_at_false:
955 return HTML.tag('i', class_="icon-false")
962 return HTML.tag('i', class_="icon-false")
956 return HTML.tag('i')
963 return HTML.tag('i')
957
964
958 #==============================================================================
965 #==============================================================================
959 # PERMS
966 # PERMS
960 #==============================================================================
967 #==============================================================================
961 from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \
968 from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \
962 HasRepoPermissionAny, HasRepoPermissionAll, HasRepoGroupPermissionAll, \
969 HasRepoPermissionAny, HasRepoPermissionAll, HasRepoGroupPermissionAll, \
963 HasRepoGroupPermissionAny, HasRepoPermissionAnyApi, get_csrf_token, \
970 HasRepoGroupPermissionAny, HasRepoPermissionAnyApi, get_csrf_token, \
964 csrf_token_key
971 csrf_token_key
965
972
966
973
967 #==============================================================================
974 #==============================================================================
968 # GRAVATAR URL
975 # GRAVATAR URL
969 #==============================================================================
976 #==============================================================================
970 class InitialsGravatar(object):
977 class InitialsGravatar(object):
971 def __init__(self, email_address, first_name, last_name, size=30,
978 def __init__(self, email_address, first_name, last_name, size=30,
972 background=None, text_color='#fff'):
979 background=None, text_color='#fff'):
973 self.size = size
980 self.size = size
974 self.first_name = first_name
981 self.first_name = first_name
975 self.last_name = last_name
982 self.last_name = last_name
976 self.email_address = email_address
983 self.email_address = email_address
977 self.background = background or self.str2color(email_address)
984 self.background = background or self.str2color(email_address)
978 self.text_color = text_color
985 self.text_color = text_color
979
986
980 def get_color_bank(self):
987 def get_color_bank(self):
981 """
988 """
982 returns a predefined list of colors that gravatars can use.
989 returns a predefined list of colors that gravatars can use.
983 Those are randomized distinct colors that guarantee readability and
990 Those are randomized distinct colors that guarantee readability and
984 uniqueness.
991 uniqueness.
985
992
986 generated with: http://phrogz.net/css/distinct-colors.html
993 generated with: http://phrogz.net/css/distinct-colors.html
987 """
994 """
988 return [
995 return [
989 '#bf3030', '#a67f53', '#00ff00', '#5989b3', '#392040', '#d90000',
996 '#bf3030', '#a67f53', '#00ff00', '#5989b3', '#392040', '#d90000',
990 '#402910', '#204020', '#79baf2', '#a700b3', '#bf6060', '#7f5320',
997 '#402910', '#204020', '#79baf2', '#a700b3', '#bf6060', '#7f5320',
991 '#008000', '#003059', '#ee00ff', '#ff0000', '#8c4b00', '#007300',
998 '#008000', '#003059', '#ee00ff', '#ff0000', '#8c4b00', '#007300',
992 '#005fb3', '#de73e6', '#ff4040', '#ffaa00', '#3df255', '#203140',
999 '#005fb3', '#de73e6', '#ff4040', '#ffaa00', '#3df255', '#203140',
993 '#47004d', '#591616', '#664400', '#59b365', '#0d2133', '#83008c',
1000 '#47004d', '#591616', '#664400', '#59b365', '#0d2133', '#83008c',
994 '#592d2d', '#bf9f60', '#73e682', '#1d3f73', '#73006b', '#402020',
1001 '#592d2d', '#bf9f60', '#73e682', '#1d3f73', '#73006b', '#402020',
995 '#b2862d', '#397341', '#597db3', '#e600d6', '#a60000', '#736039',
1002 '#b2862d', '#397341', '#597db3', '#e600d6', '#a60000', '#736039',
996 '#00b318', '#79aaf2', '#330d30', '#ff8080', '#403010', '#16591f',
1003 '#00b318', '#79aaf2', '#330d30', '#ff8080', '#403010', '#16591f',
997 '#002459', '#8c4688', '#e50000', '#ffbf40', '#00732e', '#102340',
1004 '#002459', '#8c4688', '#e50000', '#ffbf40', '#00732e', '#102340',
998 '#bf60ac', '#8c4646', '#cc8800', '#00a642', '#1d3473', '#b32d98',
1005 '#bf60ac', '#8c4646', '#cc8800', '#00a642', '#1d3473', '#b32d98',
999 '#660e00', '#ffd580', '#80ffb2', '#7391e6', '#733967', '#d97b6c',
1006 '#660e00', '#ffd580', '#80ffb2', '#7391e6', '#733967', '#d97b6c',
1000 '#8c5e00', '#59b389', '#3967e6', '#590047', '#73281d', '#665200',
1007 '#8c5e00', '#59b389', '#3967e6', '#590047', '#73281d', '#665200',
1001 '#00e67a', '#2d50b3', '#8c2377', '#734139', '#b2982d', '#16593a',
1008 '#00e67a', '#2d50b3', '#8c2377', '#734139', '#b2982d', '#16593a',
1002 '#001859', '#ff00aa', '#a65e53', '#ffcc00', '#0d3321', '#2d3959',
1009 '#001859', '#ff00aa', '#a65e53', '#ffcc00', '#0d3321', '#2d3959',
1003 '#731d56', '#401610', '#4c3d00', '#468c6c', '#002ca6', '#d936a3',
1010 '#731d56', '#401610', '#4c3d00', '#468c6c', '#002ca6', '#d936a3',
1004 '#d94c36', '#403920', '#36d9a3', '#0d1733', '#592d4a', '#993626',
1011 '#d94c36', '#403920', '#36d9a3', '#0d1733', '#592d4a', '#993626',
1005 '#cca300', '#00734d', '#46598c', '#8c005e', '#7f1100', '#8c7000',
1012 '#cca300', '#00734d', '#46598c', '#8c005e', '#7f1100', '#8c7000',
1006 '#00a66f', '#7382e6', '#b32d74', '#d9896c', '#ffe680', '#1d7362',
1013 '#00a66f', '#7382e6', '#b32d74', '#d9896c', '#ffe680', '#1d7362',
1007 '#364cd9', '#73003d', '#d93a00', '#998a4d', '#59b3a1', '#5965b3',
1014 '#364cd9', '#73003d', '#d93a00', '#998a4d', '#59b3a1', '#5965b3',
1008 '#e5007a', '#73341d', '#665f00', '#00b38f', '#0018b3', '#59163a',
1015 '#e5007a', '#73341d', '#665f00', '#00b38f', '#0018b3', '#59163a',
1009 '#b2502d', '#bfb960', '#00ffcc', '#23318c', '#a6537f', '#734939',
1016 '#b2502d', '#bfb960', '#00ffcc', '#23318c', '#a6537f', '#734939',
1010 '#b2a700', '#104036', '#3d3df2', '#402031', '#e56739', '#736f39',
1017 '#b2a700', '#104036', '#3d3df2', '#402031', '#e56739', '#736f39',
1011 '#79f2ea', '#000059', '#401029', '#4c1400', '#ffee00', '#005953',
1018 '#79f2ea', '#000059', '#401029', '#4c1400', '#ffee00', '#005953',
1012 '#101040', '#990052', '#402820', '#403d10', '#00ffee', '#0000d9',
1019 '#101040', '#990052', '#402820', '#403d10', '#00ffee', '#0000d9',
1013 '#ff80c4', '#a66953', '#eeff00', '#00ccbe', '#8080ff', '#e673a1',
1020 '#ff80c4', '#a66953', '#eeff00', '#00ccbe', '#8080ff', '#e673a1',
1014 '#a62c00', '#474d00', '#1a3331', '#46468c', '#733950', '#662900',
1021 '#a62c00', '#474d00', '#1a3331', '#46468c', '#733950', '#662900',
1015 '#858c23', '#238c85', '#0f0073', '#b20047', '#d9986c', '#becc00',
1022 '#858c23', '#238c85', '#0f0073', '#b20047', '#d9986c', '#becc00',
1016 '#396f73', '#281d73', '#ff0066', '#ff6600', '#dee673', '#59adb3',
1023 '#396f73', '#281d73', '#ff0066', '#ff6600', '#dee673', '#59adb3',
1017 '#6559b3', '#590024', '#b2622d', '#98b32d', '#36ced9', '#332d59',
1024 '#6559b3', '#590024', '#b2622d', '#98b32d', '#36ced9', '#332d59',
1018 '#40001a', '#733f1d', '#526600', '#005359', '#242040', '#bf6079',
1025 '#40001a', '#733f1d', '#526600', '#005359', '#242040', '#bf6079',
1019 '#735039', '#cef23d', '#007780', '#5630bf', '#66001b', '#b24700',
1026 '#735039', '#cef23d', '#007780', '#5630bf', '#66001b', '#b24700',
1020 '#acbf60', '#1d6273', '#25008c', '#731d34', '#a67453', '#50592d',
1027 '#acbf60', '#1d6273', '#25008c', '#731d34', '#a67453', '#50592d',
1021 '#00ccff', '#6600ff', '#ff0044', '#4c1f00', '#8a994d', '#79daf2',
1028 '#00ccff', '#6600ff', '#ff0044', '#4c1f00', '#8a994d', '#79daf2',
1022 '#a173e6', '#d93662', '#402310', '#aaff00', '#2d98b3', '#8c40ff',
1029 '#a173e6', '#d93662', '#402310', '#aaff00', '#2d98b3', '#8c40ff',
1023 '#592d39', '#ff8c40', '#354020', '#103640', '#1a0040', '#331a20',
1030 '#592d39', '#ff8c40', '#354020', '#103640', '#1a0040', '#331a20',
1024 '#331400', '#334d00', '#1d5673', '#583973', '#7f0022', '#4c3626',
1031 '#331400', '#334d00', '#1d5673', '#583973', '#7f0022', '#4c3626',
1025 '#88cc00', '#36a3d9', '#3d0073', '#d9364c', '#33241a', '#698c23',
1032 '#88cc00', '#36a3d9', '#3d0073', '#d9364c', '#33241a', '#698c23',
1026 '#5995b3', '#300059', '#e57382', '#7f3300', '#366600', '#00aaff',
1033 '#5995b3', '#300059', '#e57382', '#7f3300', '#366600', '#00aaff',
1027 '#3a1659', '#733941', '#663600', '#74b32d', '#003c59', '#7f53a6',
1034 '#3a1659', '#733941', '#663600', '#74b32d', '#003c59', '#7f53a6',
1028 '#73000f', '#ff8800', '#baf279', '#79caf2', '#291040', '#a6293a',
1035 '#73000f', '#ff8800', '#baf279', '#79caf2', '#291040', '#a6293a',
1029 '#b2742d', '#587339', '#0077b3', '#632699', '#400009', '#d9a66c',
1036 '#b2742d', '#587339', '#0077b3', '#632699', '#400009', '#d9a66c',
1030 '#294010', '#2d4a59', '#aa00ff', '#4c131b', '#b25f00', '#5ce600',
1037 '#294010', '#2d4a59', '#aa00ff', '#4c131b', '#b25f00', '#5ce600',
1031 '#267399', '#a336d9', '#990014', '#664e33', '#86bf60', '#0088ff',
1038 '#267399', '#a336d9', '#990014', '#664e33', '#86bf60', '#0088ff',
1032 '#7700b3', '#593a16', '#073300', '#1d4b73', '#ac60bf', '#e59539',
1039 '#7700b3', '#593a16', '#073300', '#1d4b73', '#ac60bf', '#e59539',
1033 '#4f8c46', '#368dd9', '#5c0073'
1040 '#4f8c46', '#368dd9', '#5c0073'
1034 ]
1041 ]
1035
1042
1036 def rgb_to_hex_color(self, rgb_tuple):
1043 def rgb_to_hex_color(self, rgb_tuple):
1037 """
1044 """
1038 Converts an rgb_tuple passed to an hex color.
1045 Converts an rgb_tuple passed to an hex color.
1039
1046
1040 :param rgb_tuple: tuple with 3 ints represents rgb color space
1047 :param rgb_tuple: tuple with 3 ints represents rgb color space
1041 """
1048 """
1042 return '#' + ("".join(map(chr, rgb_tuple)).encode('hex'))
1049 return '#' + ("".join(map(chr, rgb_tuple)).encode('hex'))
1043
1050
1044 def email_to_int_list(self, email_str):
1051 def email_to_int_list(self, email_str):
1045 """
1052 """
1046 Get every byte of the hex digest value of email and turn it to integer.
1053 Get every byte of the hex digest value of email and turn it to integer.
1047 It's going to be always between 0-255
1054 It's going to be always between 0-255
1048 """
1055 """
1049 digest = md5_safe(email_str.lower())
1056 digest = md5_safe(email_str.lower())
1050 return [int(digest[i * 2:i * 2 + 2], 16) for i in range(16)]
1057 return [int(digest[i * 2:i * 2 + 2], 16) for i in range(16)]
1051
1058
1052 def pick_color_bank_index(self, email_str, color_bank):
1059 def pick_color_bank_index(self, email_str, color_bank):
1053 return self.email_to_int_list(email_str)[0] % len(color_bank)
1060 return self.email_to_int_list(email_str)[0] % len(color_bank)
1054
1061
1055 def str2color(self, email_str):
1062 def str2color(self, email_str):
1056 """
1063 """
1057 Tries to map in a stable algorithm an email to color
1064 Tries to map in a stable algorithm an email to color
1058
1065
1059 :param email_str:
1066 :param email_str:
1060 """
1067 """
1061 color_bank = self.get_color_bank()
1068 color_bank = self.get_color_bank()
1062 # pick position (module it's length so we always find it in the
1069 # pick position (module it's length so we always find it in the
1063 # bank even if it's smaller than 256 values
1070 # bank even if it's smaller than 256 values
1064 pos = self.pick_color_bank_index(email_str, color_bank)
1071 pos = self.pick_color_bank_index(email_str, color_bank)
1065 return color_bank[pos]
1072 return color_bank[pos]
1066
1073
1067 def normalize_email(self, email_address):
1074 def normalize_email(self, email_address):
1068 import unicodedata
1075 import unicodedata
1069 # default host used to fill in the fake/missing email
1076 # default host used to fill in the fake/missing email
1070 default_host = u'localhost'
1077 default_host = u'localhost'
1071
1078
1072 if not email_address:
1079 if not email_address:
1073 email_address = u'%s@%s' % (User.DEFAULT_USER, default_host)
1080 email_address = u'%s@%s' % (User.DEFAULT_USER, default_host)
1074
1081
1075 email_address = safe_unicode(email_address)
1082 email_address = safe_unicode(email_address)
1076
1083
1077 if u'@' not in email_address:
1084 if u'@' not in email_address:
1078 email_address = u'%s@%s' % (email_address, default_host)
1085 email_address = u'%s@%s' % (email_address, default_host)
1079
1086
1080 if email_address.endswith(u'@'):
1087 if email_address.endswith(u'@'):
1081 email_address = u'%s%s' % (email_address, default_host)
1088 email_address = u'%s%s' % (email_address, default_host)
1082
1089
1083 email_address = unicodedata.normalize('NFKD', email_address)\
1090 email_address = unicodedata.normalize('NFKD', email_address)\
1084 .encode('ascii', 'ignore')
1091 .encode('ascii', 'ignore')
1085 return email_address
1092 return email_address
1086
1093
1087 def get_initials(self):
1094 def get_initials(self):
1088 """
1095 """
1089 Returns 2 letter initials calculated based on the input.
1096 Returns 2 letter initials calculated based on the input.
1090 The algorithm picks first given email address, and takes first letter
1097 The algorithm picks first given email address, and takes first letter
1091 of part before @, and then the first letter of server name. In case
1098 of part before @, and then the first letter of server name. In case
1092 the part before @ is in a format of `somestring.somestring2` it replaces
1099 the part before @ is in a format of `somestring.somestring2` it replaces
1093 the server letter with first letter of somestring2
1100 the server letter with first letter of somestring2
1094
1101
1095 In case function was initialized with both first and lastname, this
1102 In case function was initialized with both first and lastname, this
1096 overrides the extraction from email by first letter of the first and
1103 overrides the extraction from email by first letter of the first and
1097 last name. We add special logic to that functionality, In case Full name
1104 last name. We add special logic to that functionality, In case Full name
1098 is compound, like Guido Von Rossum, we use last part of the last name
1105 is compound, like Guido Von Rossum, we use last part of the last name
1099 (Von Rossum) picking `R`.
1106 (Von Rossum) picking `R`.
1100
1107
1101 Function also normalizes the non-ascii characters to they ascii
1108 Function also normalizes the non-ascii characters to they ascii
1102 representation, eg Ą => A
1109 representation, eg Ą => A
1103 """
1110 """
1104 import unicodedata
1111 import unicodedata
1105 # replace non-ascii to ascii
1112 # replace non-ascii to ascii
1106 first_name = unicodedata.normalize(
1113 first_name = unicodedata.normalize(
1107 'NFKD', safe_unicode(self.first_name)).encode('ascii', 'ignore')
1114 'NFKD', safe_unicode(self.first_name)).encode('ascii', 'ignore')
1108 last_name = unicodedata.normalize(
1115 last_name = unicodedata.normalize(
1109 'NFKD', safe_unicode(self.last_name)).encode('ascii', 'ignore')
1116 'NFKD', safe_unicode(self.last_name)).encode('ascii', 'ignore')
1110
1117
1111 # do NFKD encoding, and also make sure email has proper format
1118 # do NFKD encoding, and also make sure email has proper format
1112 email_address = self.normalize_email(self.email_address)
1119 email_address = self.normalize_email(self.email_address)
1113
1120
1114 # first push the email initials
1121 # first push the email initials
1115 prefix, server = email_address.split('@', 1)
1122 prefix, server = email_address.split('@', 1)
1116
1123
1117 # check if prefix is maybe a 'first_name.last_name' syntax
1124 # check if prefix is maybe a 'first_name.last_name' syntax
1118 _dot_split = prefix.rsplit('.', 1)
1125 _dot_split = prefix.rsplit('.', 1)
1119 if len(_dot_split) == 2 and _dot_split[1]:
1126 if len(_dot_split) == 2 and _dot_split[1]:
1120 initials = [_dot_split[0][0], _dot_split[1][0]]
1127 initials = [_dot_split[0][0], _dot_split[1][0]]
1121 else:
1128 else:
1122 initials = [prefix[0], server[0]]
1129 initials = [prefix[0], server[0]]
1123
1130
1124 # then try to replace either first_name or last_name
1131 # then try to replace either first_name or last_name
1125 fn_letter = (first_name or " ")[0].strip()
1132 fn_letter = (first_name or " ")[0].strip()
1126 ln_letter = (last_name.split(' ', 1)[-1] or " ")[0].strip()
1133 ln_letter = (last_name.split(' ', 1)[-1] or " ")[0].strip()
1127
1134
1128 if fn_letter:
1135 if fn_letter:
1129 initials[0] = fn_letter
1136 initials[0] = fn_letter
1130
1137
1131 if ln_letter:
1138 if ln_letter:
1132 initials[1] = ln_letter
1139 initials[1] = ln_letter
1133
1140
1134 return ''.join(initials).upper()
1141 return ''.join(initials).upper()
1135
1142
1136 def get_img_data_by_type(self, font_family, img_type):
1143 def get_img_data_by_type(self, font_family, img_type):
1137 default_user = """
1144 default_user = """
1138 <svg xmlns="http://www.w3.org/2000/svg"
1145 <svg xmlns="http://www.w3.org/2000/svg"
1139 version="1.1" x="0px" y="0px" width="{size}" height="{size}"
1146 version="1.1" x="0px" y="0px" width="{size}" height="{size}"
1140 viewBox="-15 -10 439.165 429.164"
1147 viewBox="-15 -10 439.165 429.164"
1141
1148
1142 xml:space="preserve"
1149 xml:space="preserve"
1143 style="background:{background};" >
1150 style="background:{background};" >
1144
1151
1145 <path d="M204.583,216.671c50.664,0,91.74-48.075,
1152 <path d="M204.583,216.671c50.664,0,91.74-48.075,
1146 91.74-107.378c0-82.237-41.074-107.377-91.74-107.377
1153 91.74-107.378c0-82.237-41.074-107.377-91.74-107.377
1147 c-50.668,0-91.74,25.14-91.74,107.377C112.844,
1154 c-50.668,0-91.74,25.14-91.74,107.377C112.844,
1148 168.596,153.916,216.671,
1155 168.596,153.916,216.671,
1149 204.583,216.671z" fill="{text_color}"/>
1156 204.583,216.671z" fill="{text_color}"/>
1150 <path d="M407.164,374.717L360.88,
1157 <path d="M407.164,374.717L360.88,
1151 270.454c-2.117-4.771-5.836-8.728-10.465-11.138l-71.83-37.392
1158 270.454c-2.117-4.771-5.836-8.728-10.465-11.138l-71.83-37.392
1152 c-1.584-0.823-3.502-0.663-4.926,0.415c-20.316,
1159 c-1.584-0.823-3.502-0.663-4.926,0.415c-20.316,
1153 15.366-44.203,23.488-69.076,23.488c-24.877,
1160 15.366-44.203,23.488-69.076,23.488c-24.877,
1154 0-48.762-8.122-69.078-23.488
1161 0-48.762-8.122-69.078-23.488
1155 c-1.428-1.078-3.346-1.238-4.93-0.415L58.75,
1162 c-1.428-1.078-3.346-1.238-4.93-0.415L58.75,
1156 259.316c-4.631,2.41-8.346,6.365-10.465,11.138L2.001,374.717
1163 259.316c-4.631,2.41-8.346,6.365-10.465,11.138L2.001,374.717
1157 c-3.191,7.188-2.537,15.412,1.75,22.005c4.285,
1164 c-3.191,7.188-2.537,15.412,1.75,22.005c4.285,
1158 6.592,11.537,10.526,19.4,10.526h362.861c7.863,0,15.117-3.936,
1165 6.592,11.537,10.526,19.4,10.526h362.861c7.863,0,15.117-3.936,
1159 19.402-10.527 C409.699,390.129,
1166 19.402-10.527 C409.699,390.129,
1160 410.355,381.902,407.164,374.717z" fill="{text_color}"/>
1167 410.355,381.902,407.164,374.717z" fill="{text_color}"/>
1161 </svg>""".format(
1168 </svg>""".format(
1162 size=self.size,
1169 size=self.size,
1163 background='#979797', # @grey4
1170 background='#979797', # @grey4
1164 text_color=self.text_color,
1171 text_color=self.text_color,
1165 font_family=font_family)
1172 font_family=font_family)
1166
1173
1167 return {
1174 return {
1168 "default_user": default_user
1175 "default_user": default_user
1169 }[img_type]
1176 }[img_type]
1170
1177
1171 def get_img_data(self, svg_type=None):
1178 def get_img_data(self, svg_type=None):
1172 """
1179 """
1173 generates the svg metadata for image
1180 generates the svg metadata for image
1174 """
1181 """
1175 fonts = [
1182 fonts = [
1176 '-apple-system',
1183 '-apple-system',
1177 'BlinkMacSystemFont',
1184 'BlinkMacSystemFont',
1178 'Segoe UI',
1185 'Segoe UI',
1179 'Roboto',
1186 'Roboto',
1180 'Oxygen-Sans',
1187 'Oxygen-Sans',
1181 'Ubuntu',
1188 'Ubuntu',
1182 'Cantarell',
1189 'Cantarell',
1183 'Helvetica Neue',
1190 'Helvetica Neue',
1184 'sans-serif'
1191 'sans-serif'
1185 ]
1192 ]
1186 font_family = ','.join(fonts)
1193 font_family = ','.join(fonts)
1187 if svg_type:
1194 if svg_type:
1188 return self.get_img_data_by_type(font_family, svg_type)
1195 return self.get_img_data_by_type(font_family, svg_type)
1189
1196
1190 initials = self.get_initials()
1197 initials = self.get_initials()
1191 img_data = """
1198 img_data = """
1192 <svg xmlns="http://www.w3.org/2000/svg" pointer-events="none"
1199 <svg xmlns="http://www.w3.org/2000/svg" pointer-events="none"
1193 width="{size}" height="{size}"
1200 width="{size}" height="{size}"
1194 style="width: 100%; height: 100%; background-color: {background}"
1201 style="width: 100%; height: 100%; background-color: {background}"
1195 viewBox="0 0 {size} {size}">
1202 viewBox="0 0 {size} {size}">
1196 <text text-anchor="middle" y="50%" x="50%" dy="0.35em"
1203 <text text-anchor="middle" y="50%" x="50%" dy="0.35em"
1197 pointer-events="auto" fill="{text_color}"
1204 pointer-events="auto" fill="{text_color}"
1198 font-family="{font_family}"
1205 font-family="{font_family}"
1199 style="font-weight: 400; font-size: {f_size}px;">{text}
1206 style="font-weight: 400; font-size: {f_size}px;">{text}
1200 </text>
1207 </text>
1201 </svg>""".format(
1208 </svg>""".format(
1202 size=self.size,
1209 size=self.size,
1203 f_size=self.size/2.05, # scale the text inside the box nicely
1210 f_size=self.size/2.05, # scale the text inside the box nicely
1204 background=self.background,
1211 background=self.background,
1205 text_color=self.text_color,
1212 text_color=self.text_color,
1206 text=initials.upper(),
1213 text=initials.upper(),
1207 font_family=font_family)
1214 font_family=font_family)
1208
1215
1209 return img_data
1216 return img_data
1210
1217
1211 def generate_svg(self, svg_type=None):
1218 def generate_svg(self, svg_type=None):
1212 img_data = self.get_img_data(svg_type)
1219 img_data = self.get_img_data(svg_type)
1213 return "data:image/svg+xml;base64,%s" % img_data.encode('base64')
1220 return "data:image/svg+xml;base64,%s" % img_data.encode('base64')
1214
1221
1215
1222
1216 def initials_gravatar(email_address, first_name, last_name, size=30):
1223 def initials_gravatar(email_address, first_name, last_name, size=30):
1217 svg_type = None
1224 svg_type = None
1218 if email_address == User.DEFAULT_USER_EMAIL:
1225 if email_address == User.DEFAULT_USER_EMAIL:
1219 svg_type = 'default_user'
1226 svg_type = 'default_user'
1220 klass = InitialsGravatar(email_address, first_name, last_name, size)
1227 klass = InitialsGravatar(email_address, first_name, last_name, size)
1221 return klass.generate_svg(svg_type=svg_type)
1228 return klass.generate_svg(svg_type=svg_type)
1222
1229
1223
1230
1224 def gravatar_url(email_address, size=30, request=None):
1231 def gravatar_url(email_address, size=30, request=None):
1225 request = get_current_request()
1232 request = get_current_request()
1226 _use_gravatar = request.call_context.visual.use_gravatar
1233 _use_gravatar = request.call_context.visual.use_gravatar
1227 _gravatar_url = request.call_context.visual.gravatar_url
1234 _gravatar_url = request.call_context.visual.gravatar_url
1228
1235
1229 _gravatar_url = _gravatar_url or User.DEFAULT_GRAVATAR_URL
1236 _gravatar_url = _gravatar_url or User.DEFAULT_GRAVATAR_URL
1230
1237
1231 email_address = email_address or User.DEFAULT_USER_EMAIL
1238 email_address = email_address or User.DEFAULT_USER_EMAIL
1232 if isinstance(email_address, unicode):
1239 if isinstance(email_address, unicode):
1233 # hashlib crashes on unicode items
1240 # hashlib crashes on unicode items
1234 email_address = safe_str(email_address)
1241 email_address = safe_str(email_address)
1235
1242
1236 # empty email or default user
1243 # empty email or default user
1237 if not email_address or email_address == User.DEFAULT_USER_EMAIL:
1244 if not email_address or email_address == User.DEFAULT_USER_EMAIL:
1238 return initials_gravatar(User.DEFAULT_USER_EMAIL, '', '', size=size)
1245 return initials_gravatar(User.DEFAULT_USER_EMAIL, '', '', size=size)
1239
1246
1240 if _use_gravatar:
1247 if _use_gravatar:
1241 # TODO: Disuse pyramid thread locals. Think about another solution to
1248 # TODO: Disuse pyramid thread locals. Think about another solution to
1242 # get the host and schema here.
1249 # get the host and schema here.
1243 request = get_current_request()
1250 request = get_current_request()
1244 tmpl = safe_str(_gravatar_url)
1251 tmpl = safe_str(_gravatar_url)
1245 tmpl = tmpl.replace('{email}', email_address)\
1252 tmpl = tmpl.replace('{email}', email_address)\
1246 .replace('{md5email}', md5_safe(email_address.lower())) \
1253 .replace('{md5email}', md5_safe(email_address.lower())) \
1247 .replace('{netloc}', request.host)\
1254 .replace('{netloc}', request.host)\
1248 .replace('{scheme}', request.scheme)\
1255 .replace('{scheme}', request.scheme)\
1249 .replace('{size}', safe_str(size))
1256 .replace('{size}', safe_str(size))
1250 return tmpl
1257 return tmpl
1251 else:
1258 else:
1252 return initials_gravatar(email_address, '', '', size=size)
1259 return initials_gravatar(email_address, '', '', size=size)
1253
1260
1254
1261
1255 class Page(_Page):
1262 class Page(_Page):
1256 """
1263 """
1257 Custom pager to match rendering style with paginator
1264 Custom pager to match rendering style with paginator
1258 """
1265 """
1259
1266
1260 def _get_pos(self, cur_page, max_page, items):
1267 def _get_pos(self, cur_page, max_page, items):
1261 edge = (items / 2) + 1
1268 edge = (items / 2) + 1
1262 if (cur_page <= edge):
1269 if (cur_page <= edge):
1263 radius = max(items / 2, items - cur_page)
1270 radius = max(items / 2, items - cur_page)
1264 elif (max_page - cur_page) < edge:
1271 elif (max_page - cur_page) < edge:
1265 radius = (items - 1) - (max_page - cur_page)
1272 radius = (items - 1) - (max_page - cur_page)
1266 else:
1273 else:
1267 radius = items / 2
1274 radius = items / 2
1268
1275
1269 left = max(1, (cur_page - (radius)))
1276 left = max(1, (cur_page - (radius)))
1270 right = min(max_page, cur_page + (radius))
1277 right = min(max_page, cur_page + (radius))
1271 return left, cur_page, right
1278 return left, cur_page, right
1272
1279
1273 def _range(self, regexp_match):
1280 def _range(self, regexp_match):
1274 """
1281 """
1275 Return range of linked pages (e.g. '1 2 [3] 4 5 6 7 8').
1282 Return range of linked pages (e.g. '1 2 [3] 4 5 6 7 8').
1276
1283
1277 Arguments:
1284 Arguments:
1278
1285
1279 regexp_match
1286 regexp_match
1280 A "re" (regular expressions) match object containing the
1287 A "re" (regular expressions) match object containing the
1281 radius of linked pages around the current page in
1288 radius of linked pages around the current page in
1282 regexp_match.group(1) as a string
1289 regexp_match.group(1) as a string
1283
1290
1284 This function is supposed to be called as a callable in
1291 This function is supposed to be called as a callable in
1285 re.sub.
1292 re.sub.
1286
1293
1287 """
1294 """
1288 radius = int(regexp_match.group(1))
1295 radius = int(regexp_match.group(1))
1289
1296
1290 # Compute the first and last page number within the radius
1297 # Compute the first and last page number within the radius
1291 # e.g. '1 .. 5 6 [7] 8 9 .. 12'
1298 # e.g. '1 .. 5 6 [7] 8 9 .. 12'
1292 # -> leftmost_page = 5
1299 # -> leftmost_page = 5
1293 # -> rightmost_page = 9
1300 # -> rightmost_page = 9
1294 leftmost_page, _cur, rightmost_page = self._get_pos(self.page,
1301 leftmost_page, _cur, rightmost_page = self._get_pos(self.page,
1295 self.last_page,
1302 self.last_page,
1296 (radius * 2) + 1)
1303 (radius * 2) + 1)
1297 nav_items = []
1304 nav_items = []
1298
1305
1299 # Create a link to the first page (unless we are on the first page
1306 # Create a link to the first page (unless we are on the first page
1300 # or there would be no need to insert '..' spacers)
1307 # or there would be no need to insert '..' spacers)
1301 if self.page != self.first_page and self.first_page < leftmost_page:
1308 if self.page != self.first_page and self.first_page < leftmost_page:
1302 nav_items.append(self._pagerlink(self.first_page, self.first_page))
1309 nav_items.append(self._pagerlink(self.first_page, self.first_page))
1303
1310
1304 # Insert dots if there are pages between the first page
1311 # Insert dots if there are pages between the first page
1305 # and the currently displayed page range
1312 # and the currently displayed page range
1306 if leftmost_page - self.first_page > 1:
1313 if leftmost_page - self.first_page > 1:
1307 # Wrap in a SPAN tag if nolink_attr is set
1314 # Wrap in a SPAN tag if nolink_attr is set
1308 text = '..'
1315 text = '..'
1309 if self.dotdot_attr:
1316 if self.dotdot_attr:
1310 text = HTML.span(c=text, **self.dotdot_attr)
1317 text = HTML.span(c=text, **self.dotdot_attr)
1311 nav_items.append(text)
1318 nav_items.append(text)
1312
1319
1313 for thispage in xrange(leftmost_page, rightmost_page + 1):
1320 for thispage in xrange(leftmost_page, rightmost_page + 1):
1314 # Hilight the current page number and do not use a link
1321 # Hilight the current page number and do not use a link
1315 if thispage == self.page:
1322 if thispage == self.page:
1316 text = '%s' % (thispage,)
1323 text = '%s' % (thispage,)
1317 # Wrap in a SPAN tag if nolink_attr is set
1324 # Wrap in a SPAN tag if nolink_attr is set
1318 if self.curpage_attr:
1325 if self.curpage_attr:
1319 text = HTML.span(c=text, **self.curpage_attr)
1326 text = HTML.span(c=text, **self.curpage_attr)
1320 nav_items.append(text)
1327 nav_items.append(text)
1321 # Otherwise create just a link to that page
1328 # Otherwise create just a link to that page
1322 else:
1329 else:
1323 text = '%s' % (thispage,)
1330 text = '%s' % (thispage,)
1324 nav_items.append(self._pagerlink(thispage, text))
1331 nav_items.append(self._pagerlink(thispage, text))
1325
1332
1326 # Insert dots if there are pages between the displayed
1333 # Insert dots if there are pages between the displayed
1327 # page numbers and the end of the page range
1334 # page numbers and the end of the page range
1328 if self.last_page - rightmost_page > 1:
1335 if self.last_page - rightmost_page > 1:
1329 text = '..'
1336 text = '..'
1330 # Wrap in a SPAN tag if nolink_attr is set
1337 # Wrap in a SPAN tag if nolink_attr is set
1331 if self.dotdot_attr:
1338 if self.dotdot_attr:
1332 text = HTML.span(c=text, **self.dotdot_attr)
1339 text = HTML.span(c=text, **self.dotdot_attr)
1333 nav_items.append(text)
1340 nav_items.append(text)
1334
1341
1335 # Create a link to the very last page (unless we are on the last
1342 # Create a link to the very last page (unless we are on the last
1336 # page or there would be no need to insert '..' spacers)
1343 # page or there would be no need to insert '..' spacers)
1337 if self.page != self.last_page and rightmost_page < self.last_page:
1344 if self.page != self.last_page and rightmost_page < self.last_page:
1338 nav_items.append(self._pagerlink(self.last_page, self.last_page))
1345 nav_items.append(self._pagerlink(self.last_page, self.last_page))
1339
1346
1340 ## prerender links
1347 ## prerender links
1341 #_page_link = url.current()
1348 #_page_link = url.current()
1342 #nav_items.append(literal('<link rel="prerender" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
1349 #nav_items.append(literal('<link rel="prerender" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
1343 #nav_items.append(literal('<link rel="prefetch" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
1350 #nav_items.append(literal('<link rel="prefetch" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
1344 return self.separator.join(nav_items)
1351 return self.separator.join(nav_items)
1345
1352
1346 def pager(self, format='~2~', page_param='page', partial_param='partial',
1353 def pager(self, format='~2~', page_param='page', partial_param='partial',
1347 show_if_single_page=False, separator=' ', onclick=None,
1354 show_if_single_page=False, separator=' ', onclick=None,
1348 symbol_first='<<', symbol_last='>>',
1355 symbol_first='<<', symbol_last='>>',
1349 symbol_previous='<', symbol_next='>',
1356 symbol_previous='<', symbol_next='>',
1350 link_attr={'class': 'pager_link', 'rel': 'prerender'},
1357 link_attr={'class': 'pager_link', 'rel': 'prerender'},
1351 curpage_attr={'class': 'pager_curpage'},
1358 curpage_attr={'class': 'pager_curpage'},
1352 dotdot_attr={'class': 'pager_dotdot'}, **kwargs):
1359 dotdot_attr={'class': 'pager_dotdot'}, **kwargs):
1353
1360
1354 self.curpage_attr = curpage_attr
1361 self.curpage_attr = curpage_attr
1355 self.separator = separator
1362 self.separator = separator
1356 self.pager_kwargs = kwargs
1363 self.pager_kwargs = kwargs
1357 self.page_param = page_param
1364 self.page_param = page_param
1358 self.partial_param = partial_param
1365 self.partial_param = partial_param
1359 self.onclick = onclick
1366 self.onclick = onclick
1360 self.link_attr = link_attr
1367 self.link_attr = link_attr
1361 self.dotdot_attr = dotdot_attr
1368 self.dotdot_attr = dotdot_attr
1362
1369
1363 # Don't show navigator if there is no more than one page
1370 # Don't show navigator if there is no more than one page
1364 if self.page_count == 0 or (self.page_count == 1 and not show_if_single_page):
1371 if self.page_count == 0 or (self.page_count == 1 and not show_if_single_page):
1365 return ''
1372 return ''
1366
1373
1367 from string import Template
1374 from string import Template
1368 # Replace ~...~ in token format by range of pages
1375 # Replace ~...~ in token format by range of pages
1369 result = re.sub(r'~(\d+)~', self._range, format)
1376 result = re.sub(r'~(\d+)~', self._range, format)
1370
1377
1371 # Interpolate '%' variables
1378 # Interpolate '%' variables
1372 result = Template(result).safe_substitute({
1379 result = Template(result).safe_substitute({
1373 'first_page': self.first_page,
1380 'first_page': self.first_page,
1374 'last_page': self.last_page,
1381 'last_page': self.last_page,
1375 'page': self.page,
1382 'page': self.page,
1376 'page_count': self.page_count,
1383 'page_count': self.page_count,
1377 'items_per_page': self.items_per_page,
1384 'items_per_page': self.items_per_page,
1378 'first_item': self.first_item,
1385 'first_item': self.first_item,
1379 'last_item': self.last_item,
1386 'last_item': self.last_item,
1380 'item_count': self.item_count,
1387 'item_count': self.item_count,
1381 'link_first': self.page > self.first_page and \
1388 'link_first': self.page > self.first_page and \
1382 self._pagerlink(self.first_page, symbol_first) or '',
1389 self._pagerlink(self.first_page, symbol_first) or '',
1383 'link_last': self.page < self.last_page and \
1390 'link_last': self.page < self.last_page and \
1384 self._pagerlink(self.last_page, symbol_last) or '',
1391 self._pagerlink(self.last_page, symbol_last) or '',
1385 'link_previous': self.previous_page and \
1392 'link_previous': self.previous_page and \
1386 self._pagerlink(self.previous_page, symbol_previous) \
1393 self._pagerlink(self.previous_page, symbol_previous) \
1387 or HTML.span(symbol_previous, class_="pg-previous disabled"),
1394 or HTML.span(symbol_previous, class_="pg-previous disabled"),
1388 'link_next': self.next_page and \
1395 'link_next': self.next_page and \
1389 self._pagerlink(self.next_page, symbol_next) \
1396 self._pagerlink(self.next_page, symbol_next) \
1390 or HTML.span(symbol_next, class_="pg-next disabled")
1397 or HTML.span(symbol_next, class_="pg-next disabled")
1391 })
1398 })
1392
1399
1393 return literal(result)
1400 return literal(result)
1394
1401
1395
1402
1396 #==============================================================================
1403 #==============================================================================
1397 # REPO PAGER, PAGER FOR REPOSITORY
1404 # REPO PAGER, PAGER FOR REPOSITORY
1398 #==============================================================================
1405 #==============================================================================
1399 class RepoPage(Page):
1406 class RepoPage(Page):
1400
1407
1401 def __init__(self, collection, page=1, items_per_page=20,
1408 def __init__(self, collection, page=1, items_per_page=20,
1402 item_count=None, url=None, **kwargs):
1409 item_count=None, url=None, **kwargs):
1403
1410
1404 """Create a "RepoPage" instance. special pager for paging
1411 """Create a "RepoPage" instance. special pager for paging
1405 repository
1412 repository
1406 """
1413 """
1407 self._url_generator = url
1414 self._url_generator = url
1408
1415
1409 # Safe the kwargs class-wide so they can be used in the pager() method
1416 # Safe the kwargs class-wide so they can be used in the pager() method
1410 self.kwargs = kwargs
1417 self.kwargs = kwargs
1411
1418
1412 # Save a reference to the collection
1419 # Save a reference to the collection
1413 self.original_collection = collection
1420 self.original_collection = collection
1414
1421
1415 self.collection = collection
1422 self.collection = collection
1416
1423
1417 # The self.page is the number of the current page.
1424 # The self.page is the number of the current page.
1418 # The first page has the number 1!
1425 # The first page has the number 1!
1419 try:
1426 try:
1420 self.page = int(page) # make it int() if we get it as a string
1427 self.page = int(page) # make it int() if we get it as a string
1421 except (ValueError, TypeError):
1428 except (ValueError, TypeError):
1422 self.page = 1
1429 self.page = 1
1423
1430
1424 self.items_per_page = items_per_page
1431 self.items_per_page = items_per_page
1425
1432
1426 # Unless the user tells us how many items the collections has
1433 # Unless the user tells us how many items the collections has
1427 # we calculate that ourselves.
1434 # we calculate that ourselves.
1428 if item_count is not None:
1435 if item_count is not None:
1429 self.item_count = item_count
1436 self.item_count = item_count
1430 else:
1437 else:
1431 self.item_count = len(self.collection)
1438 self.item_count = len(self.collection)
1432
1439
1433 # Compute the number of the first and last available page
1440 # Compute the number of the first and last available page
1434 if self.item_count > 0:
1441 if self.item_count > 0:
1435 self.first_page = 1
1442 self.first_page = 1
1436 self.page_count = int(math.ceil(float(self.item_count) /
1443 self.page_count = int(math.ceil(float(self.item_count) /
1437 self.items_per_page))
1444 self.items_per_page))
1438 self.last_page = self.first_page + self.page_count - 1
1445 self.last_page = self.first_page + self.page_count - 1
1439
1446
1440 # Make sure that the requested page number is the range of
1447 # Make sure that the requested page number is the range of
1441 # valid pages
1448 # valid pages
1442 if self.page > self.last_page:
1449 if self.page > self.last_page:
1443 self.page = self.last_page
1450 self.page = self.last_page
1444 elif self.page < self.first_page:
1451 elif self.page < self.first_page:
1445 self.page = self.first_page
1452 self.page = self.first_page
1446
1453
1447 # Note: the number of items on this page can be less than
1454 # Note: the number of items on this page can be less than
1448 # items_per_page if the last page is not full
1455 # items_per_page if the last page is not full
1449 self.first_item = max(0, (self.item_count) - (self.page *
1456 self.first_item = max(0, (self.item_count) - (self.page *
1450 items_per_page))
1457 items_per_page))
1451 self.last_item = ((self.item_count - 1) - items_per_page *
1458 self.last_item = ((self.item_count - 1) - items_per_page *
1452 (self.page - 1))
1459 (self.page - 1))
1453
1460
1454 self.items = list(self.collection[self.first_item:self.last_item + 1])
1461 self.items = list(self.collection[self.first_item:self.last_item + 1])
1455
1462
1456 # Links to previous and next page
1463 # Links to previous and next page
1457 if self.page > self.first_page:
1464 if self.page > self.first_page:
1458 self.previous_page = self.page - 1
1465 self.previous_page = self.page - 1
1459 else:
1466 else:
1460 self.previous_page = None
1467 self.previous_page = None
1461
1468
1462 if self.page < self.last_page:
1469 if self.page < self.last_page:
1463 self.next_page = self.page + 1
1470 self.next_page = self.page + 1
1464 else:
1471 else:
1465 self.next_page = None
1472 self.next_page = None
1466
1473
1467 # No items available
1474 # No items available
1468 else:
1475 else:
1469 self.first_page = None
1476 self.first_page = None
1470 self.page_count = 0
1477 self.page_count = 0
1471 self.last_page = None
1478 self.last_page = None
1472 self.first_item = None
1479 self.first_item = None
1473 self.last_item = None
1480 self.last_item = None
1474 self.previous_page = None
1481 self.previous_page = None
1475 self.next_page = None
1482 self.next_page = None
1476 self.items = []
1483 self.items = []
1477
1484
1478 # This is a subclass of the 'list' type. Initialise the list now.
1485 # This is a subclass of the 'list' type. Initialise the list now.
1479 list.__init__(self, reversed(self.items))
1486 list.__init__(self, reversed(self.items))
1480
1487
1481
1488
1482 def breadcrumb_repo_link(repo):
1489 def breadcrumb_repo_link(repo):
1483 """
1490 """
1484 Makes a breadcrumbs path link to repo
1491 Makes a breadcrumbs path link to repo
1485
1492
1486 ex::
1493 ex::
1487 group >> subgroup >> repo
1494 group >> subgroup >> repo
1488
1495
1489 :param repo: a Repository instance
1496 :param repo: a Repository instance
1490 """
1497 """
1491
1498
1492 path = [
1499 path = [
1493 link_to(group.name, route_path('repo_group_home', repo_group_name=group.group_name),
1500 link_to(group.name, route_path('repo_group_home', repo_group_name=group.group_name),
1494 title='last change:{}'.format(format_date(group.last_commit_change)))
1501 title='last change:{}'.format(format_date(group.last_commit_change)))
1495 for group in repo.groups_with_parents
1502 for group in repo.groups_with_parents
1496 ] + [
1503 ] + [
1497 link_to(repo.just_name, route_path('repo_summary', repo_name=repo.repo_name),
1504 link_to(repo.just_name, route_path('repo_summary', repo_name=repo.repo_name),
1498 title='last change:{}'.format(format_date(repo.last_commit_change)))
1505 title='last change:{}'.format(format_date(repo.last_commit_change)))
1499 ]
1506 ]
1500
1507
1501 return literal(' &raquo; '.join(path))
1508 return literal(' &raquo; '.join(path))
1502
1509
1503
1510
1504 def breadcrumb_repo_group_link(repo_group):
1511 def breadcrumb_repo_group_link(repo_group):
1505 """
1512 """
1506 Makes a breadcrumbs path link to repo
1513 Makes a breadcrumbs path link to repo
1507
1514
1508 ex::
1515 ex::
1509 group >> subgroup
1516 group >> subgroup
1510
1517
1511 :param repo_group: a Repository Group instance
1518 :param repo_group: a Repository Group instance
1512 """
1519 """
1513
1520
1514 path = [
1521 path = [
1515 link_to(group.name,
1522 link_to(group.name,
1516 route_path('repo_group_home', repo_group_name=group.group_name),
1523 route_path('repo_group_home', repo_group_name=group.group_name),
1517 title='last change:{}'.format(format_date(group.last_commit_change)))
1524 title='last change:{}'.format(format_date(group.last_commit_change)))
1518 for group in repo_group.parents
1525 for group in repo_group.parents
1519 ] + [
1526 ] + [
1520 link_to(repo_group.name,
1527 link_to(repo_group.name,
1521 route_path('repo_group_home', repo_group_name=repo_group.group_name),
1528 route_path('repo_group_home', repo_group_name=repo_group.group_name),
1522 title='last change:{}'.format(format_date(repo_group.last_commit_change)))
1529 title='last change:{}'.format(format_date(repo_group.last_commit_change)))
1523 ]
1530 ]
1524
1531
1525 return literal(' &raquo; '.join(path))
1532 return literal(' &raquo; '.join(path))
1526
1533
1527
1534
1528 def format_byte_size_binary(file_size):
1535 def format_byte_size_binary(file_size):
1529 """
1536 """
1530 Formats file/folder sizes to standard.
1537 Formats file/folder sizes to standard.
1531 """
1538 """
1532 if file_size is None:
1539 if file_size is None:
1533 file_size = 0
1540 file_size = 0
1534
1541
1535 formatted_size = format_byte_size(file_size, binary=True)
1542 formatted_size = format_byte_size(file_size, binary=True)
1536 return formatted_size
1543 return formatted_size
1537
1544
1538
1545
1539 def urlify_text(text_, safe=True):
1546 def urlify_text(text_, safe=True):
1540 """
1547 """
1541 Extrac urls from text and make html links out of them
1548 Extrac urls from text and make html links out of them
1542
1549
1543 :param text_:
1550 :param text_:
1544 """
1551 """
1545
1552
1546 url_pat = re.compile(r'''(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@#.&+]'''
1553 url_pat = re.compile(r'''(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@#.&+]'''
1547 '''|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)''')
1554 '''|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)''')
1548
1555
1549 def url_func(match_obj):
1556 def url_func(match_obj):
1550 url_full = match_obj.groups()[0]
1557 url_full = match_obj.groups()[0]
1551 return '<a href="%(url)s">%(url)s</a>' % ({'url': url_full})
1558 return '<a href="%(url)s">%(url)s</a>' % ({'url': url_full})
1552 _newtext = url_pat.sub(url_func, text_)
1559 _newtext = url_pat.sub(url_func, text_)
1553 if safe:
1560 if safe:
1554 return literal(_newtext)
1561 return literal(_newtext)
1555 return _newtext
1562 return _newtext
1556
1563
1557
1564
1558 def urlify_commits(text_, repository):
1565 def urlify_commits(text_, repository):
1559 """
1566 """
1560 Extract commit ids from text and make link from them
1567 Extract commit ids from text and make link from them
1561
1568
1562 :param text_:
1569 :param text_:
1563 :param repository: repo name to build the URL with
1570 :param repository: repo name to build the URL with
1564 """
1571 """
1565
1572
1566 URL_PAT = re.compile(r'(^|\s)([0-9a-fA-F]{12,40})($|\s)')
1573 URL_PAT = re.compile(r'(^|\s)([0-9a-fA-F]{12,40})($|\s)')
1567
1574
1568 def url_func(match_obj):
1575 def url_func(match_obj):
1569 commit_id = match_obj.groups()[1]
1576 commit_id = match_obj.groups()[1]
1570 pref = match_obj.groups()[0]
1577 pref = match_obj.groups()[0]
1571 suf = match_obj.groups()[2]
1578 suf = match_obj.groups()[2]
1572
1579
1573 tmpl = (
1580 tmpl = (
1574 '%(pref)s<a class="%(cls)s" href="%(url)s">'
1581 '%(pref)s<a class="%(cls)s" href="%(url)s">'
1575 '%(commit_id)s</a>%(suf)s'
1582 '%(commit_id)s</a>%(suf)s'
1576 )
1583 )
1577 return tmpl % {
1584 return tmpl % {
1578 'pref': pref,
1585 'pref': pref,
1579 'cls': 'revision-link',
1586 'cls': 'revision-link',
1580 'url': route_url('repo_commit', repo_name=repository, commit_id=commit_id),
1587 'url': route_url('repo_commit', repo_name=repository, commit_id=commit_id),
1581 'commit_id': commit_id,
1588 'commit_id': commit_id,
1582 'suf': suf
1589 'suf': suf
1583 }
1590 }
1584
1591
1585 newtext = URL_PAT.sub(url_func, text_)
1592 newtext = URL_PAT.sub(url_func, text_)
1586
1593
1587 return newtext
1594 return newtext
1588
1595
1589
1596
1590 def _process_url_func(match_obj, repo_name, uid, entry,
1597 def _process_url_func(match_obj, repo_name, uid, entry,
1591 return_raw_data=False, link_format='html'):
1598 return_raw_data=False, link_format='html'):
1592 pref = ''
1599 pref = ''
1593 if match_obj.group().startswith(' '):
1600 if match_obj.group().startswith(' '):
1594 pref = ' '
1601 pref = ' '
1595
1602
1596 issue_id = ''.join(match_obj.groups())
1603 issue_id = ''.join(match_obj.groups())
1597
1604
1598 if link_format == 'html':
1605 if link_format == 'html':
1599 tmpl = (
1606 tmpl = (
1600 '%(pref)s<a class="%(cls)s" href="%(url)s">'
1607 '%(pref)s<a class="%(cls)s" href="%(url)s">'
1601 '%(issue-prefix)s%(id-repr)s'
1608 '%(issue-prefix)s%(id-repr)s'
1602 '</a>')
1609 '</a>')
1603 elif link_format == 'rst':
1610 elif link_format == 'rst':
1604 tmpl = '`%(issue-prefix)s%(id-repr)s <%(url)s>`_'
1611 tmpl = '`%(issue-prefix)s%(id-repr)s <%(url)s>`_'
1605 elif link_format == 'markdown':
1612 elif link_format == 'markdown':
1606 tmpl = '[%(issue-prefix)s%(id-repr)s](%(url)s)'
1613 tmpl = '[%(issue-prefix)s%(id-repr)s](%(url)s)'
1607 else:
1614 else:
1608 raise ValueError('Bad link_format:{}'.format(link_format))
1615 raise ValueError('Bad link_format:{}'.format(link_format))
1609
1616
1610 (repo_name_cleaned,
1617 (repo_name_cleaned,
1611 parent_group_name) = RepoGroupModel()._get_group_name_and_parent(repo_name)
1618 parent_group_name) = RepoGroupModel()._get_group_name_and_parent(repo_name)
1612
1619
1613 # variables replacement
1620 # variables replacement
1614 named_vars = {
1621 named_vars = {
1615 'id': issue_id,
1622 'id': issue_id,
1616 'repo': repo_name,
1623 'repo': repo_name,
1617 'repo_name': repo_name_cleaned,
1624 'repo_name': repo_name_cleaned,
1618 'group_name': parent_group_name
1625 'group_name': parent_group_name
1619 }
1626 }
1620 # named regex variables
1627 # named regex variables
1621 named_vars.update(match_obj.groupdict())
1628 named_vars.update(match_obj.groupdict())
1622 _url = string.Template(entry['url']).safe_substitute(**named_vars)
1629 _url = string.Template(entry['url']).safe_substitute(**named_vars)
1623
1630
1624 def quote_cleaner(input_str):
1631 def quote_cleaner(input_str):
1625 """Remove quotes as it's HTML"""
1632 """Remove quotes as it's HTML"""
1626 return input_str.replace('"', '')
1633 return input_str.replace('"', '')
1627
1634
1628 data = {
1635 data = {
1629 'pref': pref,
1636 'pref': pref,
1630 'cls': quote_cleaner('issue-tracker-link'),
1637 'cls': quote_cleaner('issue-tracker-link'),
1631 'url': quote_cleaner(_url),
1638 'url': quote_cleaner(_url),
1632 'id-repr': issue_id,
1639 'id-repr': issue_id,
1633 'issue-prefix': entry['pref'],
1640 'issue-prefix': entry['pref'],
1634 'serv': entry['url'],
1641 'serv': entry['url'],
1635 }
1642 }
1636 if return_raw_data:
1643 if return_raw_data:
1637 return {
1644 return {
1638 'id': issue_id,
1645 'id': issue_id,
1639 'url': _url
1646 'url': _url
1640 }
1647 }
1641 return tmpl % data
1648 return tmpl % data
1642
1649
1643
1650
1644 def get_active_pattern_entries(repo_name):
1651 def get_active_pattern_entries(repo_name):
1645 repo = None
1652 repo = None
1646 if repo_name:
1653 if repo_name:
1647 # Retrieving repo_name to avoid invalid repo_name to explode on
1654 # Retrieving repo_name to avoid invalid repo_name to explode on
1648 # IssueTrackerSettingsModel but still passing invalid name further down
1655 # IssueTrackerSettingsModel but still passing invalid name further down
1649 repo = Repository.get_by_repo_name(repo_name, cache=True)
1656 repo = Repository.get_by_repo_name(repo_name, cache=True)
1650
1657
1651 settings_model = IssueTrackerSettingsModel(repo=repo)
1658 settings_model = IssueTrackerSettingsModel(repo=repo)
1652 active_entries = settings_model.get_settings(cache=True)
1659 active_entries = settings_model.get_settings(cache=True)
1653 return active_entries
1660 return active_entries
1654
1661
1655
1662
1656 def process_patterns(text_string, repo_name, link_format='html', active_entries=None):
1663 def process_patterns(text_string, repo_name, link_format='html', active_entries=None):
1657
1664
1658 allowed_formats = ['html', 'rst', 'markdown']
1665 allowed_formats = ['html', 'rst', 'markdown']
1659 if link_format not in allowed_formats:
1666 if link_format not in allowed_formats:
1660 raise ValueError('Link format can be only one of:{} got {}'.format(
1667 raise ValueError('Link format can be only one of:{} got {}'.format(
1661 allowed_formats, link_format))
1668 allowed_formats, link_format))
1662
1669
1663 active_entries = active_entries or get_active_pattern_entries(repo_name)
1670 active_entries = active_entries or get_active_pattern_entries(repo_name)
1664 issues_data = []
1671 issues_data = []
1665 newtext = text_string
1672 newtext = text_string
1666
1673
1667 for uid, entry in active_entries.items():
1674 for uid, entry in active_entries.items():
1668 log.debug('found issue tracker entry with uid %s', uid)
1675 log.debug('found issue tracker entry with uid %s', uid)
1669
1676
1670 if not (entry['pat'] and entry['url']):
1677 if not (entry['pat'] and entry['url']):
1671 log.debug('skipping due to missing data')
1678 log.debug('skipping due to missing data')
1672 continue
1679 continue
1673
1680
1674 log.debug('issue tracker entry: uid: `%s` PAT:%s URL:%s PREFIX:%s',
1681 log.debug('issue tracker entry: uid: `%s` PAT:%s URL:%s PREFIX:%s',
1675 uid, entry['pat'], entry['url'], entry['pref'])
1682 uid, entry['pat'], entry['url'], entry['pref'])
1676
1683
1677 try:
1684 try:
1678 pattern = re.compile(r'%s' % entry['pat'])
1685 pattern = re.compile(r'%s' % entry['pat'])
1679 except re.error:
1686 except re.error:
1680 log.exception(
1687 log.exception(
1681 'issue tracker pattern: `%s` failed to compile',
1688 'issue tracker pattern: `%s` failed to compile',
1682 entry['pat'])
1689 entry['pat'])
1683 continue
1690 continue
1684
1691
1685 data_func = partial(
1692 data_func = partial(
1686 _process_url_func, repo_name=repo_name, entry=entry, uid=uid,
1693 _process_url_func, repo_name=repo_name, entry=entry, uid=uid,
1687 return_raw_data=True)
1694 return_raw_data=True)
1688
1695
1689 for match_obj in pattern.finditer(text_string):
1696 for match_obj in pattern.finditer(text_string):
1690 issues_data.append(data_func(match_obj))
1697 issues_data.append(data_func(match_obj))
1691
1698
1692 url_func = partial(
1699 url_func = partial(
1693 _process_url_func, repo_name=repo_name, entry=entry, uid=uid,
1700 _process_url_func, repo_name=repo_name, entry=entry, uid=uid,
1694 link_format=link_format)
1701 link_format=link_format)
1695
1702
1696 newtext = pattern.sub(url_func, newtext)
1703 newtext = pattern.sub(url_func, newtext)
1697 log.debug('processed prefix:uid `%s`', uid)
1704 log.debug('processed prefix:uid `%s`', uid)
1698
1705
1699 return newtext, issues_data
1706 return newtext, issues_data
1700
1707
1701
1708
1702 def urlify_commit_message(commit_text, repository=None, active_pattern_entries=None):
1709 def urlify_commit_message(commit_text, repository=None, active_pattern_entries=None):
1703 """
1710 """
1704 Parses given text message and makes proper links.
1711 Parses given text message and makes proper links.
1705 issues are linked to given issue-server, and rest is a commit link
1712 issues are linked to given issue-server, and rest is a commit link
1706
1713
1707 :param commit_text:
1714 :param commit_text:
1708 :param repository:
1715 :param repository:
1709 """
1716 """
1710 def escaper(string):
1717 def escaper(string):
1711 return string.replace('<', '&lt;').replace('>', '&gt;')
1718 return string.replace('<', '&lt;').replace('>', '&gt;')
1712
1719
1713 newtext = escaper(commit_text)
1720 newtext = escaper(commit_text)
1714
1721
1715 # extract http/https links and make them real urls
1722 # extract http/https links and make them real urls
1716 newtext = urlify_text(newtext, safe=False)
1723 newtext = urlify_text(newtext, safe=False)
1717
1724
1718 # urlify commits - extract commit ids and make link out of them, if we have
1725 # urlify commits - extract commit ids and make link out of them, if we have
1719 # the scope of repository present.
1726 # the scope of repository present.
1720 if repository:
1727 if repository:
1721 newtext = urlify_commits(newtext, repository)
1728 newtext = urlify_commits(newtext, repository)
1722
1729
1723 # process issue tracker patterns
1730 # process issue tracker patterns
1724 newtext, issues = process_patterns(newtext, repository or '',
1731 newtext, issues = process_patterns(newtext, repository or '',
1725 active_entries=active_pattern_entries)
1732 active_entries=active_pattern_entries)
1726
1733
1727 return literal(newtext)
1734 return literal(newtext)
1728
1735
1729
1736
1730 def render_binary(repo_name, file_obj):
1737 def render_binary(repo_name, file_obj):
1731 """
1738 """
1732 Choose how to render a binary file
1739 Choose how to render a binary file
1733 """
1740 """
1734
1741
1735 filename = file_obj.name
1742 filename = file_obj.name
1736
1743
1737 # images
1744 # images
1738 for ext in ['*.png', '*.jpg', '*.ico', '*.gif']:
1745 for ext in ['*.png', '*.jpg', '*.ico', '*.gif']:
1739 if fnmatch.fnmatch(filename, pat=ext):
1746 if fnmatch.fnmatch(filename, pat=ext):
1740 alt = escape(filename)
1747 alt = escape(filename)
1741 src = route_path(
1748 src = route_path(
1742 'repo_file_raw', repo_name=repo_name,
1749 'repo_file_raw', repo_name=repo_name,
1743 commit_id=file_obj.commit.raw_id,
1750 commit_id=file_obj.commit.raw_id,
1744 f_path=file_obj.path)
1751 f_path=file_obj.path)
1745 return literal(
1752 return literal(
1746 '<img class="rendered-binary" alt="{}" src="{}">'.format(alt, src))
1753 '<img class="rendered-binary" alt="{}" src="{}">'.format(alt, src))
1747
1754
1748
1755
1749 def renderer_from_filename(filename, exclude=None):
1756 def renderer_from_filename(filename, exclude=None):
1750 """
1757 """
1751 choose a renderer based on filename, this works only for text based files
1758 choose a renderer based on filename, this works only for text based files
1752 """
1759 """
1753
1760
1754 # ipython
1761 # ipython
1755 for ext in ['*.ipynb']:
1762 for ext in ['*.ipynb']:
1756 if fnmatch.fnmatch(filename, pat=ext):
1763 if fnmatch.fnmatch(filename, pat=ext):
1757 return 'jupyter'
1764 return 'jupyter'
1758
1765
1759 is_markup = MarkupRenderer.renderer_from_filename(filename, exclude=exclude)
1766 is_markup = MarkupRenderer.renderer_from_filename(filename, exclude=exclude)
1760 if is_markup:
1767 if is_markup:
1761 return is_markup
1768 return is_markup
1762 return None
1769 return None
1763
1770
1764
1771
1765 def render(source, renderer='rst', mentions=False, relative_urls=None,
1772 def render(source, renderer='rst', mentions=False, relative_urls=None,
1766 repo_name=None):
1773 repo_name=None):
1767
1774
1768 def maybe_convert_relative_links(html_source):
1775 def maybe_convert_relative_links(html_source):
1769 if relative_urls:
1776 if relative_urls:
1770 return relative_links(html_source, relative_urls)
1777 return relative_links(html_source, relative_urls)
1771 return html_source
1778 return html_source
1772
1779
1773 if renderer == 'plain':
1780 if renderer == 'plain':
1774 return literal(
1781 return literal(
1775 MarkupRenderer.plain(source, leading_newline=False))
1782 MarkupRenderer.plain(source, leading_newline=False))
1776
1783
1777 elif renderer == 'rst':
1784 elif renderer == 'rst':
1778 if repo_name:
1785 if repo_name:
1779 # process patterns on comments if we pass in repo name
1786 # process patterns on comments if we pass in repo name
1780 source, issues = process_patterns(
1787 source, issues = process_patterns(
1781 source, repo_name, link_format='rst')
1788 source, repo_name, link_format='rst')
1782
1789
1783 return literal(
1790 return literal(
1784 '<div class="rst-block">%s</div>' %
1791 '<div class="rst-block">%s</div>' %
1785 maybe_convert_relative_links(
1792 maybe_convert_relative_links(
1786 MarkupRenderer.rst(source, mentions=mentions)))
1793 MarkupRenderer.rst(source, mentions=mentions)))
1787
1794
1788 elif renderer == 'markdown':
1795 elif renderer == 'markdown':
1789 if repo_name:
1796 if repo_name:
1790 # process patterns on comments if we pass in repo name
1797 # process patterns on comments if we pass in repo name
1791 source, issues = process_patterns(
1798 source, issues = process_patterns(
1792 source, repo_name, link_format='markdown')
1799 source, repo_name, link_format='markdown')
1793
1800
1794 return literal(
1801 return literal(
1795 '<div class="markdown-block">%s</div>' %
1802 '<div class="markdown-block">%s</div>' %
1796 maybe_convert_relative_links(
1803 maybe_convert_relative_links(
1797 MarkupRenderer.markdown(source, flavored=True,
1804 MarkupRenderer.markdown(source, flavored=True,
1798 mentions=mentions)))
1805 mentions=mentions)))
1799
1806
1800 elif renderer == 'jupyter':
1807 elif renderer == 'jupyter':
1801 return literal(
1808 return literal(
1802 '<div class="ipynb">%s</div>' %
1809 '<div class="ipynb">%s</div>' %
1803 maybe_convert_relative_links(
1810 maybe_convert_relative_links(
1804 MarkupRenderer.jupyter(source)))
1811 MarkupRenderer.jupyter(source)))
1805
1812
1806 # None means just show the file-source
1813 # None means just show the file-source
1807 return None
1814 return None
1808
1815
1809
1816
1810 def commit_status(repo, commit_id):
1817 def commit_status(repo, commit_id):
1811 return ChangesetStatusModel().get_status(repo, commit_id)
1818 return ChangesetStatusModel().get_status(repo, commit_id)
1812
1819
1813
1820
1814 def commit_status_lbl(commit_status):
1821 def commit_status_lbl(commit_status):
1815 return dict(ChangesetStatus.STATUSES).get(commit_status)
1822 return dict(ChangesetStatus.STATUSES).get(commit_status)
1816
1823
1817
1824
1818 def commit_time(repo_name, commit_id):
1825 def commit_time(repo_name, commit_id):
1819 repo = Repository.get_by_repo_name(repo_name)
1826 repo = Repository.get_by_repo_name(repo_name)
1820 commit = repo.get_commit(commit_id=commit_id)
1827 commit = repo.get_commit(commit_id=commit_id)
1821 return commit.date
1828 return commit.date
1822
1829
1823
1830
1824 def get_permission_name(key):
1831 def get_permission_name(key):
1825 return dict(Permission.PERMS).get(key)
1832 return dict(Permission.PERMS).get(key)
1826
1833
1827
1834
1828 def journal_filter_help(request):
1835 def journal_filter_help(request):
1829 _ = request.translate
1836 _ = request.translate
1830 from rhodecode.lib.audit_logger import ACTIONS
1837 from rhodecode.lib.audit_logger import ACTIONS
1831 actions = '\n'.join(textwrap.wrap(', '.join(sorted(ACTIONS.keys())), 80))
1838 actions = '\n'.join(textwrap.wrap(', '.join(sorted(ACTIONS.keys())), 80))
1832
1839
1833 return _(
1840 return _(
1834 'Example filter terms:\n' +
1841 'Example filter terms:\n' +
1835 ' repository:vcs\n' +
1842 ' repository:vcs\n' +
1836 ' username:marcin\n' +
1843 ' username:marcin\n' +
1837 ' username:(NOT marcin)\n' +
1844 ' username:(NOT marcin)\n' +
1838 ' action:*push*\n' +
1845 ' action:*push*\n' +
1839 ' ip:127.0.0.1\n' +
1846 ' ip:127.0.0.1\n' +
1840 ' date:20120101\n' +
1847 ' date:20120101\n' +
1841 ' date:[20120101100000 TO 20120102]\n' +
1848 ' date:[20120101100000 TO 20120102]\n' +
1842 '\n' +
1849 '\n' +
1843 'Actions: {actions}\n' +
1850 'Actions: {actions}\n' +
1844 '\n' +
1851 '\n' +
1845 'Generate wildcards using \'*\' character:\n' +
1852 'Generate wildcards using \'*\' character:\n' +
1846 ' "repository:vcs*" - search everything starting with \'vcs\'\n' +
1853 ' "repository:vcs*" - search everything starting with \'vcs\'\n' +
1847 ' "repository:*vcs*" - search for repository containing \'vcs\'\n' +
1854 ' "repository:*vcs*" - search for repository containing \'vcs\'\n' +
1848 '\n' +
1855 '\n' +
1849 'Optional AND / OR operators in queries\n' +
1856 'Optional AND / OR operators in queries\n' +
1850 ' "repository:vcs OR repository:test"\n' +
1857 ' "repository:vcs OR repository:test"\n' +
1851 ' "username:test AND repository:test*"\n'
1858 ' "username:test AND repository:test*"\n'
1852 ).format(actions=actions)
1859 ).format(actions=actions)
1853
1860
1854
1861
1855 def not_mapped_error(repo_name):
1862 def not_mapped_error(repo_name):
1856 from rhodecode.translation import _
1863 from rhodecode.translation import _
1857 flash(_('%s repository is not mapped to db perhaps'
1864 flash(_('%s repository is not mapped to db perhaps'
1858 ' it was created or renamed from the filesystem'
1865 ' it was created or renamed from the filesystem'
1859 ' please run the application again'
1866 ' please run the application again'
1860 ' in order to rescan repositories') % repo_name, category='error')
1867 ' in order to rescan repositories') % repo_name, category='error')
1861
1868
1862
1869
1863 def ip_range(ip_addr):
1870 def ip_range(ip_addr):
1864 from rhodecode.model.db import UserIpMap
1871 from rhodecode.model.db import UserIpMap
1865 s, e = UserIpMap._get_ip_range(ip_addr)
1872 s, e = UserIpMap._get_ip_range(ip_addr)
1866 return '%s - %s' % (s, e)
1873 return '%s - %s' % (s, e)
1867
1874
1868
1875
1869 def form(url, method='post', needs_csrf_token=True, **attrs):
1876 def form(url, method='post', needs_csrf_token=True, **attrs):
1870 """Wrapper around webhelpers.tags.form to prevent CSRF attacks."""
1877 """Wrapper around webhelpers.tags.form to prevent CSRF attacks."""
1871 if method.lower() != 'get' and needs_csrf_token:
1878 if method.lower() != 'get' and needs_csrf_token:
1872 raise Exception(
1879 raise Exception(
1873 'Forms to POST/PUT/DELETE endpoints should have (in general) a ' +
1880 'Forms to POST/PUT/DELETE endpoints should have (in general) a ' +
1874 'CSRF token. If the endpoint does not require such token you can ' +
1881 'CSRF token. If the endpoint does not require such token you can ' +
1875 'explicitly set the parameter needs_csrf_token to false.')
1882 'explicitly set the parameter needs_csrf_token to false.')
1876
1883
1877 return wh_form(url, method=method, **attrs)
1884 return wh_form(url, method=method, **attrs)
1878
1885
1879
1886
1880 def secure_form(form_url, method="POST", multipart=False, **attrs):
1887 def secure_form(form_url, method="POST", multipart=False, **attrs):
1881 """Start a form tag that points the action to an url. This
1888 """Start a form tag that points the action to an url. This
1882 form tag will also include the hidden field containing
1889 form tag will also include the hidden field containing
1883 the auth token.
1890 the auth token.
1884
1891
1885 The url options should be given either as a string, or as a
1892 The url options should be given either as a string, or as a
1886 ``url()`` function. The method for the form defaults to POST.
1893 ``url()`` function. The method for the form defaults to POST.
1887
1894
1888 Options:
1895 Options:
1889
1896
1890 ``multipart``
1897 ``multipart``
1891 If set to True, the enctype is set to "multipart/form-data".
1898 If set to True, the enctype is set to "multipart/form-data".
1892 ``method``
1899 ``method``
1893 The method to use when submitting the form, usually either
1900 The method to use when submitting the form, usually either
1894 "GET" or "POST". If "PUT", "DELETE", or another verb is used, a
1901 "GET" or "POST". If "PUT", "DELETE", or another verb is used, a
1895 hidden input with name _method is added to simulate the verb
1902 hidden input with name _method is added to simulate the verb
1896 over POST.
1903 over POST.
1897
1904
1898 """
1905 """
1899 from webhelpers.pylonslib.secure_form import insecure_form
1906 from webhelpers.pylonslib.secure_form import insecure_form
1900
1907
1901 if 'request' in attrs:
1908 if 'request' in attrs:
1902 session = attrs['request'].session
1909 session = attrs['request'].session
1903 del attrs['request']
1910 del attrs['request']
1904 else:
1911 else:
1905 raise ValueError(
1912 raise ValueError(
1906 'Calling this form requires request= to be passed as argument')
1913 'Calling this form requires request= to be passed as argument')
1907
1914
1908 form = insecure_form(form_url, method, multipart, **attrs)
1915 form = insecure_form(form_url, method, multipart, **attrs)
1909 token = literal(
1916 token = literal(
1910 '<input type="hidden" id="{}" name="{}" value="{}">'.format(
1917 '<input type="hidden" id="{}" name="{}" value="{}">'.format(
1911 csrf_token_key, csrf_token_key, get_csrf_token(session)))
1918 csrf_token_key, csrf_token_key, get_csrf_token(session)))
1912
1919
1913 return literal("%s\n%s" % (form, token))
1920 return literal("%s\n%s" % (form, token))
1914
1921
1915
1922
1916 def dropdownmenu(name, selected, options, enable_filter=False, **attrs):
1923 def dropdownmenu(name, selected, options, enable_filter=False, **attrs):
1917 select_html = select(name, selected, options, **attrs)
1924 select_html = select(name, selected, options, **attrs)
1918 select2 = """
1925 select2 = """
1919 <script>
1926 <script>
1920 $(document).ready(function() {
1927 $(document).ready(function() {
1921 $('#%s').select2({
1928 $('#%s').select2({
1922 containerCssClass: 'drop-menu',
1929 containerCssClass: 'drop-menu',
1923 dropdownCssClass: 'drop-menu-dropdown',
1930 dropdownCssClass: 'drop-menu-dropdown',
1924 dropdownAutoWidth: true%s
1931 dropdownAutoWidth: true%s
1925 });
1932 });
1926 });
1933 });
1927 </script>
1934 </script>
1928 """
1935 """
1929 filter_option = """,
1936 filter_option = """,
1930 minimumResultsForSearch: -1
1937 minimumResultsForSearch: -1
1931 """
1938 """
1932 input_id = attrs.get('id') or name
1939 input_id = attrs.get('id') or name
1933 filter_enabled = "" if enable_filter else filter_option
1940 filter_enabled = "" if enable_filter else filter_option
1934 select_script = literal(select2 % (input_id, filter_enabled))
1941 select_script = literal(select2 % (input_id, filter_enabled))
1935
1942
1936 return literal(select_html+select_script)
1943 return literal(select_html+select_script)
1937
1944
1938
1945
1939 def get_visual_attr(tmpl_context_var, attr_name):
1946 def get_visual_attr(tmpl_context_var, attr_name):
1940 """
1947 """
1941 A safe way to get a variable from visual variable of template context
1948 A safe way to get a variable from visual variable of template context
1942
1949
1943 :param tmpl_context_var: instance of tmpl_context, usually present as `c`
1950 :param tmpl_context_var: instance of tmpl_context, usually present as `c`
1944 :param attr_name: name of the attribute we fetch from the c.visual
1951 :param attr_name: name of the attribute we fetch from the c.visual
1945 """
1952 """
1946 visual = getattr(tmpl_context_var, 'visual', None)
1953 visual = getattr(tmpl_context_var, 'visual', None)
1947 if not visual:
1954 if not visual:
1948 return
1955 return
1949 else:
1956 else:
1950 return getattr(visual, attr_name, None)
1957 return getattr(visual, attr_name, None)
1951
1958
1952
1959
1953 def get_last_path_part(file_node):
1960 def get_last_path_part(file_node):
1954 if not file_node.path:
1961 if not file_node.path:
1955 return u'/'
1962 return u'/'
1956
1963
1957 path = safe_unicode(file_node.path.split('/')[-1])
1964 path = safe_unicode(file_node.path.split('/')[-1])
1958 return u'../' + path
1965 return u'../' + path
1959
1966
1960
1967
1961 def route_url(*args, **kwargs):
1968 def route_url(*args, **kwargs):
1962 """
1969 """
1963 Wrapper around pyramids `route_url` (fully qualified url) function.
1970 Wrapper around pyramids `route_url` (fully qualified url) function.
1964 """
1971 """
1965 req = get_current_request()
1972 req = get_current_request()
1966 return req.route_url(*args, **kwargs)
1973 return req.route_url(*args, **kwargs)
1967
1974
1968
1975
1969 def route_path(*args, **kwargs):
1976 def route_path(*args, **kwargs):
1970 """
1977 """
1971 Wrapper around pyramids `route_path` function.
1978 Wrapper around pyramids `route_path` function.
1972 """
1979 """
1973 req = get_current_request()
1980 req = get_current_request()
1974 return req.route_path(*args, **kwargs)
1981 return req.route_path(*args, **kwargs)
1975
1982
1976
1983
1977 def route_path_or_none(*args, **kwargs):
1984 def route_path_or_none(*args, **kwargs):
1978 try:
1985 try:
1979 return route_path(*args, **kwargs)
1986 return route_path(*args, **kwargs)
1980 except KeyError:
1987 except KeyError:
1981 return None
1988 return None
1982
1989
1983
1990
1984 def current_route_path(request, **kw):
1991 def current_route_path(request, **kw):
1985 new_args = request.GET.mixed()
1992 new_args = request.GET.mixed()
1986 new_args.update(kw)
1993 new_args.update(kw)
1987 return request.current_route_path(_query=new_args)
1994 return request.current_route_path(_query=new_args)
1988
1995
1989
1996
1990 def api_call_example(method, args):
1997 def api_call_example(method, args):
1991 """
1998 """
1992 Generates an API call example via CURL
1999 Generates an API call example via CURL
1993 """
2000 """
1994 args_json = json.dumps(OrderedDict([
2001 args_json = json.dumps(OrderedDict([
1995 ('id', 1),
2002 ('id', 1),
1996 ('auth_token', 'SECRET'),
2003 ('auth_token', 'SECRET'),
1997 ('method', method),
2004 ('method', method),
1998 ('args', args)
2005 ('args', args)
1999 ]))
2006 ]))
2000 return literal(
2007 return literal(
2001 "curl {api_url} -X POST -H 'content-type:text/plain' --data-binary '{data}'"
2008 "curl {api_url} -X POST -H 'content-type:text/plain' --data-binary '{data}'"
2002 "<br/><br/>SECRET can be found in <a href=\"{token_url}\">auth-tokens</a> page, "
2009 "<br/><br/>SECRET can be found in <a href=\"{token_url}\">auth-tokens</a> page, "
2003 "and needs to be of `api calls` role."
2010 "and needs to be of `api calls` role."
2004 .format(
2011 .format(
2005 api_url=route_url('apiv2'),
2012 api_url=route_url('apiv2'),
2006 token_url=route_url('my_account_auth_tokens'),
2013 token_url=route_url('my_account_auth_tokens'),
2007 data=args_json))
2014 data=args_json))
2008
2015
2009
2016
2010 def notification_description(notification, request):
2017 def notification_description(notification, request):
2011 """
2018 """
2012 Generate notification human readable description based on notification type
2019 Generate notification human readable description based on notification type
2013 """
2020 """
2014 from rhodecode.model.notification import NotificationModel
2021 from rhodecode.model.notification import NotificationModel
2015 return NotificationModel().make_description(
2022 return NotificationModel().make_description(
2016 notification, translate=request.translate)
2023 notification, translate=request.translate)
2017
2024
2018
2025
2019 def go_import_header(request, db_repo=None):
2026 def go_import_header(request, db_repo=None):
2020 """
2027 """
2021 Creates a header for go-import functionality in Go Lang
2028 Creates a header for go-import functionality in Go Lang
2022 """
2029 """
2023
2030
2024 if not db_repo:
2031 if not db_repo:
2025 return
2032 return
2026 if 'go-get' not in request.GET:
2033 if 'go-get' not in request.GET:
2027 return
2034 return
2028
2035
2029 clone_url = db_repo.clone_url()
2036 clone_url = db_repo.clone_url()
2030 prefix = re.split(r'^https?:\/\/', clone_url)[-1]
2037 prefix = re.split(r'^https?:\/\/', clone_url)[-1]
2031 # we have a repo and go-get flag,
2038 # we have a repo and go-get flag,
2032 return literal('<meta name="go-import" content="{} {} {}">'.format(
2039 return literal('<meta name="go-import" content="{} {} {}">'.format(
2033 prefix, db_repo.repo_type, clone_url))
2040 prefix, db_repo.repo_type, clone_url))
2034
2041
2035
2042
2036 def reviewer_as_json(*args, **kwargs):
2043 def reviewer_as_json(*args, **kwargs):
2037 from rhodecode.apps.repository.utils import reviewer_as_json as _reviewer_as_json
2044 from rhodecode.apps.repository.utils import reviewer_as_json as _reviewer_as_json
2038 return _reviewer_as_json(*args, **kwargs)
2045 return _reviewer_as_json(*args, **kwargs)
2039
2046
2040
2047
2041 def get_repo_view_type(request):
2048 def get_repo_view_type(request):
2042 route_name = request.matched_route.name
2049 route_name = request.matched_route.name
2043 route_to_view_type = {
2050 route_to_view_type = {
2044 'repo_changelog': 'changelog',
2051 'repo_changelog': 'changelog',
2045 'repo_files': 'files',
2052 'repo_files': 'files',
2046 'repo_summary': 'summary',
2053 'repo_summary': 'summary',
2047 'repo_commit': 'commit'
2054 'repo_commit': 'commit'
2048 }
2055 }
2049
2056
2050 return route_to_view_type.get(route_name)
2057 return route_to_view_type.get(route_name)
@@ -1,2583 +1,2584 b''
1 //Primary CSS
1 //Primary CSS
2
2
3 //--- IMPORTS ------------------//
3 //--- IMPORTS ------------------//
4
4
5 @import 'helpers';
5 @import 'helpers';
6 @import 'mixins';
6 @import 'mixins';
7 @import 'rcicons';
7 @import 'rcicons';
8 @import 'variables';
8 @import 'variables';
9 @import 'bootstrap-variables';
9 @import 'bootstrap-variables';
10 @import 'form-bootstrap';
10 @import 'form-bootstrap';
11 @import 'codemirror';
11 @import 'codemirror';
12 @import 'legacy_code_styles';
12 @import 'legacy_code_styles';
13 @import 'readme-box';
13 @import 'readme-box';
14 @import 'progress-bar';
14 @import 'progress-bar';
15
15
16 @import 'type';
16 @import 'type';
17 @import 'alerts';
17 @import 'alerts';
18 @import 'buttons';
18 @import 'buttons';
19 @import 'tags';
19 @import 'tags';
20 @import 'code-block';
20 @import 'code-block';
21 @import 'examples';
21 @import 'examples';
22 @import 'login';
22 @import 'login';
23 @import 'main-content';
23 @import 'main-content';
24 @import 'select2';
24 @import 'select2';
25 @import 'comments';
25 @import 'comments';
26 @import 'panels-bootstrap';
26 @import 'panels-bootstrap';
27 @import 'panels';
27 @import 'panels';
28 @import 'deform';
28 @import 'deform';
29
29
30 //--- BASE ------------------//
30 //--- BASE ------------------//
31 .noscript-error {
31 .noscript-error {
32 top: 0;
32 top: 0;
33 left: 0;
33 left: 0;
34 width: 100%;
34 width: 100%;
35 z-index: 101;
35 z-index: 101;
36 text-align: center;
36 text-align: center;
37 font-size: 120%;
37 font-size: 120%;
38 color: white;
38 color: white;
39 background-color: @alert2;
39 background-color: @alert2;
40 padding: 5px 0 5px 0;
40 padding: 5px 0 5px 0;
41 font-weight: @text-semibold-weight;
41 font-weight: @text-semibold-weight;
42 font-family: @text-semibold;
42 font-family: @text-semibold;
43 }
43 }
44
44
45 html {
45 html {
46 display: table;
46 display: table;
47 height: 100%;
47 height: 100%;
48 width: 100%;
48 width: 100%;
49 }
49 }
50
50
51 body {
51 body {
52 display: table-cell;
52 display: table-cell;
53 width: 100%;
53 width: 100%;
54 }
54 }
55
55
56 //--- LAYOUT ------------------//
56 //--- LAYOUT ------------------//
57
57
58 .hidden{
58 .hidden{
59 display: none !important;
59 display: none !important;
60 }
60 }
61
61
62 .box{
62 .box{
63 float: left;
63 float: left;
64 width: 100%;
64 width: 100%;
65 }
65 }
66
66
67 .browser-header {
67 .browser-header {
68 clear: both;
68 clear: both;
69 }
69 }
70 .main {
70 .main {
71 clear: both;
71 clear: both;
72 padding:0 0 @pagepadding;
72 padding:0 0 @pagepadding;
73 height: auto;
73 height: auto;
74
74
75 &:after { //clearfix
75 &:after { //clearfix
76 content:"";
76 content:"";
77 clear:both;
77 clear:both;
78 width:100%;
78 width:100%;
79 display:block;
79 display:block;
80 }
80 }
81 }
81 }
82
82
83 .action-link{
83 .action-link{
84 margin-left: @padding;
84 margin-left: @padding;
85 padding-left: @padding;
85 padding-left: @padding;
86 border-left: @border-thickness solid @border-default-color;
86 border-left: @border-thickness solid @border-default-color;
87 }
87 }
88
88
89 input + .action-link, .action-link.first{
89 input + .action-link, .action-link.first{
90 border-left: none;
90 border-left: none;
91 }
91 }
92
92
93 .action-link.last{
93 .action-link.last{
94 margin-right: @padding;
94 margin-right: @padding;
95 padding-right: @padding;
95 padding-right: @padding;
96 }
96 }
97
97
98 .action-link.active,
98 .action-link.active,
99 .action-link.active a{
99 .action-link.active a{
100 color: @grey4;
100 color: @grey4;
101 }
101 }
102
102
103 .action-link.disabled {
103 .action-link.disabled {
104 color: @grey4;
104 color: @grey4;
105 cursor: inherit;
105 cursor: inherit;
106 }
106 }
107
107
108 .clipboard-action {
108 .clipboard-action {
109 cursor: pointer;
109 cursor: pointer;
110 }
110 }
111
111
112 ul.simple-list{
112 ul.simple-list{
113 list-style: none;
113 list-style: none;
114 margin: 0;
114 margin: 0;
115 padding: 0;
115 padding: 0;
116 }
116 }
117
117
118 .main-content {
118 .main-content {
119 padding-bottom: @pagepadding;
119 padding-bottom: @pagepadding;
120 }
120 }
121
121
122 .wide-mode-wrapper {
122 .wide-mode-wrapper {
123 max-width:4000px !important;
123 max-width:4000px !important;
124 }
124 }
125
125
126 .wrapper {
126 .wrapper {
127 position: relative;
127 position: relative;
128 max-width: @wrapper-maxwidth;
128 max-width: @wrapper-maxwidth;
129 margin: 0 auto;
129 margin: 0 auto;
130 }
130 }
131
131
132 #content {
132 #content {
133 clear: both;
133 clear: both;
134 padding: 0 @contentpadding;
134 padding: 0 @contentpadding;
135 }
135 }
136
136
137 .advanced-settings-fields{
137 .advanced-settings-fields{
138 input{
138 input{
139 margin-left: @textmargin;
139 margin-left: @textmargin;
140 margin-right: @padding/2;
140 margin-right: @padding/2;
141 }
141 }
142 }
142 }
143
143
144 .cs_files_title {
144 .cs_files_title {
145 margin: @pagepadding 0 0;
145 margin: @pagepadding 0 0;
146 }
146 }
147
147
148 input.inline[type="file"] {
148 input.inline[type="file"] {
149 display: inline;
149 display: inline;
150 }
150 }
151
151
152 .error_page {
152 .error_page {
153 margin: 10% auto;
153 margin: 10% auto;
154
154
155 h1 {
155 h1 {
156 color: @grey2;
156 color: @grey2;
157 }
157 }
158
158
159 .alert {
159 .alert {
160 margin: @padding 0;
160 margin: @padding 0;
161 }
161 }
162
162
163 .error-branding {
163 .error-branding {
164 color: @grey4;
164 color: @grey4;
165 font-weight: @text-semibold-weight;
165 font-weight: @text-semibold-weight;
166 font-family: @text-semibold;
166 font-family: @text-semibold;
167 }
167 }
168
168
169 .error_message {
169 .error_message {
170 font-family: @text-regular;
170 font-family: @text-regular;
171 }
171 }
172
172
173 .sidebar {
173 .sidebar {
174 min-height: 275px;
174 min-height: 275px;
175 margin: 0;
175 margin: 0;
176 padding: 0 0 @sidebarpadding @sidebarpadding;
176 padding: 0 0 @sidebarpadding @sidebarpadding;
177 border: none;
177 border: none;
178 }
178 }
179
179
180 .main-content {
180 .main-content {
181 position: relative;
181 position: relative;
182 margin: 0 @sidebarpadding @sidebarpadding;
182 margin: 0 @sidebarpadding @sidebarpadding;
183 padding: 0 0 0 @sidebarpadding;
183 padding: 0 0 0 @sidebarpadding;
184 border-left: @border-thickness solid @grey5;
184 border-left: @border-thickness solid @grey5;
185
185
186 @media (max-width:767px) {
186 @media (max-width:767px) {
187 clear: both;
187 clear: both;
188 width: 100%;
188 width: 100%;
189 margin: 0;
189 margin: 0;
190 border: none;
190 border: none;
191 }
191 }
192 }
192 }
193
193
194 .inner-column {
194 .inner-column {
195 float: left;
195 float: left;
196 width: 29.75%;
196 width: 29.75%;
197 min-height: 150px;
197 min-height: 150px;
198 margin: @sidebarpadding 2% 0 0;
198 margin: @sidebarpadding 2% 0 0;
199 padding: 0 2% 0 0;
199 padding: 0 2% 0 0;
200 border-right: @border-thickness solid @grey5;
200 border-right: @border-thickness solid @grey5;
201
201
202 @media (max-width:767px) {
202 @media (max-width:767px) {
203 clear: both;
203 clear: both;
204 width: 100%;
204 width: 100%;
205 border: none;
205 border: none;
206 }
206 }
207
207
208 ul {
208 ul {
209 padding-left: 1.25em;
209 padding-left: 1.25em;
210 }
210 }
211
211
212 &:last-child {
212 &:last-child {
213 margin: @sidebarpadding 0 0;
213 margin: @sidebarpadding 0 0;
214 border: none;
214 border: none;
215 }
215 }
216
216
217 h4 {
217 h4 {
218 margin: 0 0 @padding;
218 margin: 0 0 @padding;
219 font-weight: @text-semibold-weight;
219 font-weight: @text-semibold-weight;
220 font-family: @text-semibold;
220 font-family: @text-semibold;
221 }
221 }
222 }
222 }
223 }
223 }
224 .error-page-logo {
224 .error-page-logo {
225 width: 130px;
225 width: 130px;
226 height: 160px;
226 height: 160px;
227 }
227 }
228
228
229 // HEADER
229 // HEADER
230 .header {
230 .header {
231
231
232 // TODO: johbo: Fix login pages, so that they work without a min-height
232 // TODO: johbo: Fix login pages, so that they work without a min-height
233 // for the header and then remove the min-height. I chose a smaller value
233 // for the header and then remove the min-height. I chose a smaller value
234 // intentionally here to avoid rendering issues in the main navigation.
234 // intentionally here to avoid rendering issues in the main navigation.
235 min-height: 49px;
235 min-height: 49px;
236
236
237 position: relative;
237 position: relative;
238 vertical-align: bottom;
238 vertical-align: bottom;
239 padding: 0 @header-padding;
239 padding: 0 @header-padding;
240 background-color: @grey1;
240 background-color: @grey1;
241 color: @grey5;
241 color: @grey5;
242
242
243 .title {
243 .title {
244 overflow: visible;
244 overflow: visible;
245 }
245 }
246
246
247 &:before,
247 &:before,
248 &:after {
248 &:after {
249 content: "";
249 content: "";
250 clear: both;
250 clear: both;
251 width: 100%;
251 width: 100%;
252 }
252 }
253
253
254 // TODO: johbo: Avoids breaking "Repositories" chooser
254 // TODO: johbo: Avoids breaking "Repositories" chooser
255 .select2-container .select2-choice .select2-arrow {
255 .select2-container .select2-choice .select2-arrow {
256 display: none;
256 display: none;
257 }
257 }
258 }
258 }
259
259
260 #header-inner {
260 #header-inner {
261 &.title {
261 &.title {
262 margin: 0;
262 margin: 0;
263 }
263 }
264 &:before,
264 &:before,
265 &:after {
265 &:after {
266 content: "";
266 content: "";
267 clear: both;
267 clear: both;
268 }
268 }
269 }
269 }
270
270
271 // Gists
271 // Gists
272 #files_data {
272 #files_data {
273 clear: both; //for firefox
273 clear: both; //for firefox
274 }
274 }
275 #gistid {
275 #gistid {
276 margin-right: @padding;
276 margin-right: @padding;
277 }
277 }
278
278
279 // Global Settings Editor
279 // Global Settings Editor
280 .textarea.editor {
280 .textarea.editor {
281 float: left;
281 float: left;
282 position: relative;
282 position: relative;
283 max-width: @texteditor-width;
283 max-width: @texteditor-width;
284
284
285 select {
285 select {
286 position: absolute;
286 position: absolute;
287 top:10px;
287 top:10px;
288 right:0;
288 right:0;
289 }
289 }
290
290
291 .CodeMirror {
291 .CodeMirror {
292 margin: 0;
292 margin: 0;
293 }
293 }
294
294
295 .help-block {
295 .help-block {
296 margin: 0 0 @padding;
296 margin: 0 0 @padding;
297 padding:.5em;
297 padding:.5em;
298 background-color: @grey6;
298 background-color: @grey6;
299 &.pre-formatting {
299 &.pre-formatting {
300 white-space: pre;
300 white-space: pre;
301 }
301 }
302 }
302 }
303 }
303 }
304
304
305 ul.auth_plugins {
305 ul.auth_plugins {
306 margin: @padding 0 @padding @legend-width;
306 margin: @padding 0 @padding @legend-width;
307 padding: 0;
307 padding: 0;
308
308
309 li {
309 li {
310 margin-bottom: @padding;
310 margin-bottom: @padding;
311 line-height: 1em;
311 line-height: 1em;
312 list-style-type: none;
312 list-style-type: none;
313
313
314 .auth_buttons .btn {
314 .auth_buttons .btn {
315 margin-right: @padding;
315 margin-right: @padding;
316 }
316 }
317
317
318 }
318 }
319 }
319 }
320
320
321
321
322 // My Account PR list
322 // My Account PR list
323
323
324 #show_closed {
324 #show_closed {
325 margin: 0 1em 0 0;
325 margin: 0 1em 0 0;
326 }
326 }
327
327
328 .pullrequestlist {
328 .pullrequestlist {
329 .closed {
329 .closed {
330 background-color: @grey6;
330 background-color: @grey6;
331 }
331 }
332 .td-status {
332 .td-status {
333 padding-left: .5em;
333 padding-left: .5em;
334 }
334 }
335 .log-container .truncate {
335 .log-container .truncate {
336 height: 2.75em;
336 height: 2.75em;
337 white-space: pre-line;
337 white-space: pre-line;
338 }
338 }
339 table.rctable .user {
339 table.rctable .user {
340 padding-left: 0;
340 padding-left: 0;
341 }
341 }
342 table.rctable {
342 table.rctable {
343 td.td-description,
343 td.td-description,
344 .rc-user {
344 .rc-user {
345 min-width: auto;
345 min-width: auto;
346 }
346 }
347 }
347 }
348 }
348 }
349
349
350 // Pull Requests
350 // Pull Requests
351
351
352 .pullrequests_section_head {
352 .pullrequests_section_head {
353 display: block;
353 display: block;
354 clear: both;
354 clear: both;
355 margin: @padding 0;
355 margin: @padding 0;
356 font-weight: @text-bold-weight;
356 font-weight: @text-bold-weight;
357 font-family: @text-bold;
357 font-family: @text-bold;
358 }
358 }
359
359
360 .pr-origininfo, .pr-targetinfo {
360 .pr-origininfo, .pr-targetinfo {
361 position: relative;
361 position: relative;
362
362
363 .tag {
363 .tag {
364 display: inline-block;
364 display: inline-block;
365 margin: 0 1em .5em 0;
365 margin: 0 1em .5em 0;
366 }
366 }
367
367
368 .clone-url {
368 .clone-url {
369 display: inline-block;
369 display: inline-block;
370 margin: 0 0 .5em 0;
370 margin: 0 0 .5em 0;
371 padding: 0;
371 padding: 0;
372 line-height: 1.2em;
372 line-height: 1.2em;
373 }
373 }
374 }
374 }
375
375
376 .pr-mergeinfo {
376 .pr-mergeinfo {
377 min-width: 95% !important;
377 min-width: 95% !important;
378 padding: 0 !important;
378 padding: 0 !important;
379 border: 0;
379 border: 0;
380 }
380 }
381 .pr-mergeinfo-copy {
381 .pr-mergeinfo-copy {
382 padding: 0 0;
382 padding: 0 0;
383 }
383 }
384
384
385 .pr-pullinfo {
385 .pr-pullinfo {
386 min-width: 95% !important;
386 min-width: 95% !important;
387 padding: 0 !important;
387 padding: 0 !important;
388 border: 0;
388 border: 0;
389 }
389 }
390 .pr-pullinfo-copy {
390 .pr-pullinfo-copy {
391 padding: 0 0;
391 padding: 0 0;
392 }
392 }
393
393
394
394
395 #pr-title-input {
395 #pr-title-input {
396 width: 72%;
396 width: 72%;
397 font-size: 1em;
397 font-size: 1em;
398 margin: 0;
398 margin: 0;
399 padding: 0 0 0 @padding/4;
399 padding: 0 0 0 @padding/4;
400 line-height: 1.7em;
400 line-height: 1.7em;
401 color: @text-color;
401 color: @text-color;
402 letter-spacing: .02em;
402 letter-spacing: .02em;
403 font-weight: @text-bold-weight;
403 font-weight: @text-bold-weight;
404 font-family: @text-bold;
404 font-family: @text-bold;
405 }
405 }
406
406
407 #pullrequest_title {
407 #pullrequest_title {
408 width: 100%;
408 width: 100%;
409 box-sizing: border-box;
409 box-sizing: border-box;
410 }
410 }
411
411
412 #pr_open_message {
412 #pr_open_message {
413 border: @border-thickness solid #fff;
413 border: @border-thickness solid #fff;
414 border-radius: @border-radius;
414 border-radius: @border-radius;
415 padding: @padding-large-vertical @padding-large-vertical @padding-large-vertical 0;
415 padding: @padding-large-vertical @padding-large-vertical @padding-large-vertical 0;
416 text-align: left;
416 text-align: left;
417 overflow: hidden;
417 overflow: hidden;
418 }
418 }
419
419
420 .pr-submit-button {
420 .pr-submit-button {
421 float: right;
421 float: right;
422 margin: 0 0 0 5px;
422 margin: 0 0 0 5px;
423 }
423 }
424
424
425 .pr-spacing-container {
425 .pr-spacing-container {
426 padding: 20px;
426 padding: 20px;
427 clear: both
427 clear: both
428 }
428 }
429
429
430 #pr-description-input {
430 #pr-description-input {
431 margin-bottom: 0;
431 margin-bottom: 0;
432 }
432 }
433
433
434 .pr-description-label {
434 .pr-description-label {
435 vertical-align: top;
435 vertical-align: top;
436 }
436 }
437
437
438 .perms_section_head {
438 .perms_section_head {
439 min-width: 625px;
439 min-width: 625px;
440
440
441 h2 {
441 h2 {
442 margin-bottom: 0;
442 margin-bottom: 0;
443 }
443 }
444
444
445 .label-checkbox {
445 .label-checkbox {
446 float: left;
446 float: left;
447 }
447 }
448
448
449 &.field {
449 &.field {
450 margin: @space 0 @padding;
450 margin: @space 0 @padding;
451 }
451 }
452
452
453 &:first-child.field {
453 &:first-child.field {
454 margin-top: 0;
454 margin-top: 0;
455
455
456 .label {
456 .label {
457 margin-top: 0;
457 margin-top: 0;
458 padding-top: 0;
458 padding-top: 0;
459 }
459 }
460
460
461 .radios {
461 .radios {
462 padding-top: 0;
462 padding-top: 0;
463 }
463 }
464 }
464 }
465
465
466 .radios {
466 .radios {
467 position: relative;
467 position: relative;
468 width: 505px;
468 width: 505px;
469 }
469 }
470 }
470 }
471
471
472 //--- MODULES ------------------//
472 //--- MODULES ------------------//
473
473
474
474
475 // Server Announcement
475 // Server Announcement
476 #server-announcement {
476 #server-announcement {
477 width: 95%;
477 width: 95%;
478 margin: @padding auto;
478 margin: @padding auto;
479 padding: @padding;
479 padding: @padding;
480 border-width: 2px;
480 border-width: 2px;
481 border-style: solid;
481 border-style: solid;
482 .border-radius(2px);
482 .border-radius(2px);
483 font-weight: @text-bold-weight;
483 font-weight: @text-bold-weight;
484 font-family: @text-bold;
484 font-family: @text-bold;
485
485
486 &.info { border-color: @alert4; background-color: @alert4-inner; }
486 &.info { border-color: @alert4; background-color: @alert4-inner; }
487 &.warning { border-color: @alert3; background-color: @alert3-inner; }
487 &.warning { border-color: @alert3; background-color: @alert3-inner; }
488 &.error { border-color: @alert2; background-color: @alert2-inner; }
488 &.error { border-color: @alert2; background-color: @alert2-inner; }
489 &.success { border-color: @alert1; background-color: @alert1-inner; }
489 &.success { border-color: @alert1; background-color: @alert1-inner; }
490 &.neutral { border-color: @grey3; background-color: @grey6; }
490 &.neutral { border-color: @grey3; background-color: @grey6; }
491 }
491 }
492
492
493 // Fixed Sidebar Column
493 // Fixed Sidebar Column
494 .sidebar-col-wrapper {
494 .sidebar-col-wrapper {
495 padding-left: @sidebar-all-width;
495 padding-left: @sidebar-all-width;
496
496
497 .sidebar {
497 .sidebar {
498 width: @sidebar-width;
498 width: @sidebar-width;
499 margin-left: -@sidebar-all-width;
499 margin-left: -@sidebar-all-width;
500 }
500 }
501 }
501 }
502
502
503 .sidebar-col-wrapper.scw-small {
503 .sidebar-col-wrapper.scw-small {
504 padding-left: @sidebar-small-all-width;
504 padding-left: @sidebar-small-all-width;
505
505
506 .sidebar {
506 .sidebar {
507 width: @sidebar-small-width;
507 width: @sidebar-small-width;
508 margin-left: -@sidebar-small-all-width;
508 margin-left: -@sidebar-small-all-width;
509 }
509 }
510 }
510 }
511
511
512
512
513 // FOOTER
513 // FOOTER
514 #footer {
514 #footer {
515 padding: 0;
515 padding: 0;
516 text-align: center;
516 text-align: center;
517 vertical-align: middle;
517 vertical-align: middle;
518 color: @grey2;
518 color: @grey2;
519 font-size: 11px;
519 font-size: 11px;
520
520
521 p {
521 p {
522 margin: 0;
522 margin: 0;
523 padding: 1em;
523 padding: 1em;
524 line-height: 1em;
524 line-height: 1em;
525 }
525 }
526
526
527 .server-instance { //server instance
527 .server-instance { //server instance
528 display: none;
528 display: none;
529 }
529 }
530
530
531 .title {
531 .title {
532 float: none;
532 float: none;
533 margin: 0 auto;
533 margin: 0 auto;
534 }
534 }
535 }
535 }
536
536
537 button.close {
537 button.close {
538 padding: 0;
538 padding: 0;
539 cursor: pointer;
539 cursor: pointer;
540 background: transparent;
540 background: transparent;
541 border: 0;
541 border: 0;
542 .box-shadow(none);
542 .box-shadow(none);
543 -webkit-appearance: none;
543 -webkit-appearance: none;
544 }
544 }
545
545
546 .close {
546 .close {
547 float: right;
547 float: right;
548 font-size: 21px;
548 font-size: 21px;
549 font-family: @text-bootstrap;
549 font-family: @text-bootstrap;
550 line-height: 1em;
550 line-height: 1em;
551 font-weight: bold;
551 font-weight: bold;
552 color: @grey2;
552 color: @grey2;
553
553
554 &:hover,
554 &:hover,
555 &:focus {
555 &:focus {
556 color: @grey1;
556 color: @grey1;
557 text-decoration: none;
557 text-decoration: none;
558 cursor: pointer;
558 cursor: pointer;
559 }
559 }
560 }
560 }
561
561
562 // GRID
562 // GRID
563 .sorting,
563 .sorting,
564 .sorting_desc,
564 .sorting_desc,
565 .sorting_asc {
565 .sorting_asc {
566 cursor: pointer;
566 cursor: pointer;
567 }
567 }
568 .sorting_desc:after {
568 .sorting_desc:after {
569 content: "\00A0\25B2";
569 content: "\00A0\25B2";
570 font-size: .75em;
570 font-size: .75em;
571 }
571 }
572 .sorting_asc:after {
572 .sorting_asc:after {
573 content: "\00A0\25BC";
573 content: "\00A0\25BC";
574 font-size: .68em;
574 font-size: .68em;
575 }
575 }
576
576
577
577
578 .user_auth_tokens {
578 .user_auth_tokens {
579
579
580 &.truncate {
580 &.truncate {
581 white-space: nowrap;
581 white-space: nowrap;
582 overflow: hidden;
582 overflow: hidden;
583 text-overflow: ellipsis;
583 text-overflow: ellipsis;
584 }
584 }
585
585
586 .fields .field .input {
586 .fields .field .input {
587 margin: 0;
587 margin: 0;
588 }
588 }
589
589
590 input#description {
590 input#description {
591 width: 100px;
591 width: 100px;
592 margin: 0;
592 margin: 0;
593 }
593 }
594
594
595 .drop-menu {
595 .drop-menu {
596 // TODO: johbo: Remove this, should work out of the box when
596 // TODO: johbo: Remove this, should work out of the box when
597 // having multiple inputs inline
597 // having multiple inputs inline
598 margin: 0 0 0 5px;
598 margin: 0 0 0 5px;
599 }
599 }
600 }
600 }
601 #user_list_table {
601 #user_list_table {
602 .closed {
602 .closed {
603 background-color: @grey6;
603 background-color: @grey6;
604 }
604 }
605 }
605 }
606
606
607
607
608 input, textarea {
608 input, textarea {
609 &.disabled {
609 &.disabled {
610 opacity: .5;
610 opacity: .5;
611 }
611 }
612
612
613 &:hover {
613 &:hover {
614 border-color: @grey3;
614 border-color: @grey3;
615 box-shadow: @button-shadow;
615 box-shadow: @button-shadow;
616 }
616 }
617
617
618 &:focus {
618 &:focus {
619 border-color: @rcblue;
619 border-color: @rcblue;
620 box-shadow: @button-shadow;
620 box-shadow: @button-shadow;
621 }
621 }
622 }
622 }
623
623
624 // remove extra padding in firefox
624 // remove extra padding in firefox
625 input::-moz-focus-inner { border:0; padding:0 }
625 input::-moz-focus-inner { border:0; padding:0 }
626
626
627 .adjacent input {
627 .adjacent input {
628 margin-bottom: @padding;
628 margin-bottom: @padding;
629 }
629 }
630
630
631 .permissions_boxes {
631 .permissions_boxes {
632 display: block;
632 display: block;
633 }
633 }
634
634
635 //FORMS
635 //FORMS
636
636
637 .medium-inline,
637 .medium-inline,
638 input#description.medium-inline {
638 input#description.medium-inline {
639 display: inline;
639 display: inline;
640 width: @medium-inline-input-width;
640 width: @medium-inline-input-width;
641 min-width: 100px;
641 min-width: 100px;
642 }
642 }
643
643
644 select {
644 select {
645 //reset
645 //reset
646 -webkit-appearance: none;
646 -webkit-appearance: none;
647 -moz-appearance: none;
647 -moz-appearance: none;
648
648
649 display: inline-block;
649 display: inline-block;
650 height: 28px;
650 height: 28px;
651 width: auto;
651 width: auto;
652 margin: 0 @padding @padding 0;
652 margin: 0 @padding @padding 0;
653 padding: 0 18px 0 8px;
653 padding: 0 18px 0 8px;
654 line-height:1em;
654 line-height:1em;
655 font-size: @basefontsize;
655 font-size: @basefontsize;
656 border: @border-thickness solid @grey5;
656 border: @border-thickness solid @grey5;
657 border-radius: @border-radius;
657 border-radius: @border-radius;
658 background:white url("../images/dt-arrow-dn.png") no-repeat 100% 50%;
658 background:white url("../images/dt-arrow-dn.png") no-repeat 100% 50%;
659 color: @grey4;
659 color: @grey4;
660 box-shadow: @button-shadow;
660 box-shadow: @button-shadow;
661
661
662 &:after {
662 &:after {
663 content: "\00A0\25BE";
663 content: "\00A0\25BE";
664 }
664 }
665
665
666 &:focus, &:hover {
666 &:focus, &:hover {
667 outline: none;
667 outline: none;
668 border-color: @grey4;
668 border-color: @grey4;
669 color: @rcdarkblue;
669 color: @rcdarkblue;
670 }
670 }
671 }
671 }
672
672
673 option {
673 option {
674 &:focus {
674 &:focus {
675 outline: none;
675 outline: none;
676 }
676 }
677 }
677 }
678
678
679 input,
679 input,
680 textarea {
680 textarea {
681 padding: @input-padding;
681 padding: @input-padding;
682 border: @input-border-thickness solid @border-highlight-color;
682 border: @input-border-thickness solid @border-highlight-color;
683 .border-radius (@border-radius);
683 .border-radius (@border-radius);
684 font-family: @text-light;
684 font-family: @text-light;
685 font-size: @basefontsize;
685 font-size: @basefontsize;
686
686
687 &.input-sm {
687 &.input-sm {
688 padding: 5px;
688 padding: 5px;
689 }
689 }
690
690
691 &#description {
691 &#description {
692 min-width: @input-description-minwidth;
692 min-width: @input-description-minwidth;
693 min-height: 1em;
693 min-height: 1em;
694 padding: 10px;
694 padding: 10px;
695 }
695 }
696 }
696 }
697
697
698 .field-sm {
698 .field-sm {
699 input,
699 input,
700 textarea {
700 textarea {
701 padding: 5px;
701 padding: 5px;
702 }
702 }
703 }
703 }
704
704
705 textarea {
705 textarea {
706 display: block;
706 display: block;
707 clear: both;
707 clear: both;
708 width: 100%;
708 width: 100%;
709 min-height: 100px;
709 min-height: 100px;
710 margin-bottom: @padding;
710 margin-bottom: @padding;
711 .box-sizing(border-box);
711 .box-sizing(border-box);
712 overflow: auto;
712 overflow: auto;
713 }
713 }
714
714
715 label {
715 label {
716 font-family: @text-light;
716 font-family: @text-light;
717 }
717 }
718
718
719 // GRAVATARS
719 // GRAVATARS
720 // centers gravatar on username to the right
720 // centers gravatar on username to the right
721
721
722 .gravatar {
722 .gravatar {
723 display: inline;
723 display: inline;
724 min-width: 16px;
724 min-width: 16px;
725 min-height: 16px;
725 min-height: 16px;
726 margin: -5px 0;
726 margin: -5px 0;
727 padding: 0;
727 padding: 0;
728 line-height: 1em;
728 line-height: 1em;
729 box-sizing: content-box;
729 box-sizing: content-box;
730 border-radius: 50%;
730 border-radius: 50%;
731
731
732 &.gravatar-large {
732 &.gravatar-large {
733 margin: -0.5em .25em -0.5em 0;
733 margin: -0.5em .25em -0.5em 0;
734 }
734 }
735
735
736 & + .user {
736 & + .user {
737 display: inline;
737 display: inline;
738 margin: 0;
738 margin: 0;
739 padding: 0 0 0 .17em;
739 padding: 0 0 0 .17em;
740 line-height: 1em;
740 line-height: 1em;
741 }
741 }
742 }
742 }
743
743
744 .user-inline-data {
744 .user-inline-data {
745 display: inline-block;
745 display: inline-block;
746 float: left;
746 float: left;
747 padding-left: .5em;
747 padding-left: .5em;
748 line-height: 1.3em;
748 line-height: 1.3em;
749 }
749 }
750
750
751 .rc-user { // gravatar + user wrapper
751 .rc-user { // gravatar + user wrapper
752 float: left;
752 float: left;
753 position: relative;
753 position: relative;
754 min-width: 100px;
754 min-width: 100px;
755 max-width: 200px;
755 max-width: 200px;
756 min-height: (@gravatar-size + @border-thickness * 2); // account for border
756 min-height: (@gravatar-size + @border-thickness * 2); // account for border
757 display: block;
757 display: block;
758 padding: 0 0 0 (@gravatar-size + @basefontsize/2 + @border-thickness * 2);
758 padding: 0 0 0 (@gravatar-size + @basefontsize/2 + @border-thickness * 2);
759
759
760
760
761 .gravatar {
761 .gravatar {
762 display: block;
762 display: block;
763 position: absolute;
763 position: absolute;
764 top: 0;
764 top: 0;
765 left: 0;
765 left: 0;
766 min-width: @gravatar-size;
766 min-width: @gravatar-size;
767 min-height: @gravatar-size;
767 min-height: @gravatar-size;
768 margin: 0;
768 margin: 0;
769 }
769 }
770
770
771 .user {
771 .user {
772 display: block;
772 display: block;
773 max-width: 175px;
773 max-width: 175px;
774 padding-top: 2px;
774 padding-top: 2px;
775 overflow: hidden;
775 overflow: hidden;
776 text-overflow: ellipsis;
776 text-overflow: ellipsis;
777 }
777 }
778 }
778 }
779
779
780 .gist-gravatar,
780 .gist-gravatar,
781 .journal_container {
781 .journal_container {
782 .gravatar-large {
782 .gravatar-large {
783 margin: 0 .5em -10px 0;
783 margin: 0 .5em -10px 0;
784 }
784 }
785 }
785 }
786
786
787
787
788 // ADMIN SETTINGS
788 // ADMIN SETTINGS
789
789
790 // Tag Patterns
790 // Tag Patterns
791 .tag_patterns {
791 .tag_patterns {
792 .tag_input {
792 .tag_input {
793 margin-bottom: @padding;
793 margin-bottom: @padding;
794 }
794 }
795 }
795 }
796
796
797 .locked_input {
797 .locked_input {
798 position: relative;
798 position: relative;
799
799
800 input {
800 input {
801 display: inline;
801 display: inline;
802 margin: 3px 5px 0px 0px;
802 margin: 3px 5px 0px 0px;
803 }
803 }
804
804
805 br {
805 br {
806 display: none;
806 display: none;
807 }
807 }
808
808
809 .error-message {
809 .error-message {
810 float: left;
810 float: left;
811 width: 100%;
811 width: 100%;
812 }
812 }
813
813
814 .lock_input_button {
814 .lock_input_button {
815 display: inline;
815 display: inline;
816 }
816 }
817
817
818 .help-block {
818 .help-block {
819 clear: both;
819 clear: both;
820 }
820 }
821 }
821 }
822
822
823 // Notifications
823 // Notifications
824
824
825 .notifications_buttons {
825 .notifications_buttons {
826 margin: 0 0 @space 0;
826 margin: 0 0 @space 0;
827 padding: 0;
827 padding: 0;
828
828
829 .btn {
829 .btn {
830 display: inline-block;
830 display: inline-block;
831 }
831 }
832 }
832 }
833
833
834 .notification-list {
834 .notification-list {
835
835
836 div {
836 div {
837 display: inline-block;
837 display: inline-block;
838 vertical-align: middle;
838 vertical-align: middle;
839 }
839 }
840
840
841 .container {
841 .container {
842 display: block;
842 display: block;
843 margin: 0 0 @padding 0;
843 margin: 0 0 @padding 0;
844 }
844 }
845
845
846 .delete-notifications {
846 .delete-notifications {
847 margin-left: @padding;
847 margin-left: @padding;
848 text-align: right;
848 text-align: right;
849 cursor: pointer;
849 cursor: pointer;
850 }
850 }
851
851
852 .read-notifications {
852 .read-notifications {
853 margin-left: @padding/2;
853 margin-left: @padding/2;
854 text-align: right;
854 text-align: right;
855 width: 35px;
855 width: 35px;
856 cursor: pointer;
856 cursor: pointer;
857 }
857 }
858
858
859 .icon-minus-sign {
859 .icon-minus-sign {
860 color: @alert2;
860 color: @alert2;
861 }
861 }
862
862
863 .icon-ok-sign {
863 .icon-ok-sign {
864 color: @alert1;
864 color: @alert1;
865 }
865 }
866 }
866 }
867
867
868 .user_settings {
868 .user_settings {
869 float: left;
869 float: left;
870 clear: both;
870 clear: both;
871 display: block;
871 display: block;
872 width: 100%;
872 width: 100%;
873
873
874 .gravatar_box {
874 .gravatar_box {
875 margin-bottom: @padding;
875 margin-bottom: @padding;
876
876
877 &:after {
877 &:after {
878 content: " ";
878 content: " ";
879 clear: both;
879 clear: both;
880 width: 100%;
880 width: 100%;
881 }
881 }
882 }
882 }
883
883
884 .fields .field {
884 .fields .field {
885 clear: both;
885 clear: both;
886 }
886 }
887 }
887 }
888
888
889 .advanced_settings {
889 .advanced_settings {
890 margin-bottom: @space;
890 margin-bottom: @space;
891
891
892 .help-block {
892 .help-block {
893 margin-left: 0;
893 margin-left: 0;
894 }
894 }
895
895
896 button + .help-block {
896 button + .help-block {
897 margin-top: @padding;
897 margin-top: @padding;
898 }
898 }
899 }
899 }
900
900
901 // admin settings radio buttons and labels
901 // admin settings radio buttons and labels
902 .label-2 {
902 .label-2 {
903 float: left;
903 float: left;
904 width: @label2-width;
904 width: @label2-width;
905
905
906 label {
906 label {
907 color: @grey1;
907 color: @grey1;
908 }
908 }
909 }
909 }
910 .checkboxes {
910 .checkboxes {
911 float: left;
911 float: left;
912 width: @checkboxes-width;
912 width: @checkboxes-width;
913 margin-bottom: @padding;
913 margin-bottom: @padding;
914
914
915 .checkbox {
915 .checkbox {
916 width: 100%;
916 width: 100%;
917
917
918 label {
918 label {
919 margin: 0;
919 margin: 0;
920 padding: 0;
920 padding: 0;
921 }
921 }
922 }
922 }
923
923
924 .checkbox + .checkbox {
924 .checkbox + .checkbox {
925 display: inline-block;
925 display: inline-block;
926 }
926 }
927
927
928 label {
928 label {
929 margin-right: 1em;
929 margin-right: 1em;
930 }
930 }
931 }
931 }
932
932
933 // CHANGELOG
933 // CHANGELOG
934 .container_header {
934 .container_header {
935 float: left;
935 float: left;
936 display: block;
936 display: block;
937 width: 100%;
937 width: 100%;
938 margin: @padding 0 @padding;
938 margin: @padding 0 @padding;
939
939
940 #filter_changelog {
940 #filter_changelog {
941 float: left;
941 float: left;
942 margin-right: @padding;
942 margin-right: @padding;
943 }
943 }
944
944
945 .breadcrumbs_light {
945 .breadcrumbs_light {
946 display: inline-block;
946 display: inline-block;
947 }
947 }
948 }
948 }
949
949
950 .info_box {
950 .info_box {
951 float: right;
951 float: right;
952 }
952 }
953
953
954
954
955 #graph_nodes {
955 #graph_nodes {
956 padding-top: 43px;
956 padding-top: 43px;
957 }
957 }
958
958
959 #graph_content{
959 #graph_content{
960
960
961 // adjust for table headers so that graph renders properly
961 // adjust for table headers so that graph renders properly
962 // #graph_nodes padding - table cell padding
962 // #graph_nodes padding - table cell padding
963 padding-top: (@space - (@basefontsize * 2.4));
963 padding-top: (@space - (@basefontsize * 2.4));
964
964
965 &.graph_full_width {
965 &.graph_full_width {
966 width: 100%;
966 width: 100%;
967 max-width: 100%;
967 max-width: 100%;
968 }
968 }
969 }
969 }
970
970
971 #graph {
971 #graph {
972 .flag_status {
972 .flag_status {
973 margin: 0;
973 margin: 0;
974 }
974 }
975
975
976 .pagination-left {
976 .pagination-left {
977 float: left;
977 float: left;
978 clear: both;
978 clear: both;
979 }
979 }
980
980
981 .log-container {
981 .log-container {
982 max-width: 345px;
982 max-width: 345px;
983
983
984 .message{
984 .message{
985 max-width: 340px;
985 max-width: 340px;
986 }
986 }
987 }
987 }
988
988
989 .graph-col-wrapper {
989 .graph-col-wrapper {
990 padding-left: 110px;
990 padding-left: 110px;
991
991
992 #graph_nodes {
992 #graph_nodes {
993 width: 100px;
993 width: 100px;
994 margin-left: -110px;
994 margin-left: -110px;
995 float: left;
995 float: left;
996 clear: left;
996 clear: left;
997 }
997 }
998 }
998 }
999
999
1000 .load-more-commits {
1000 .load-more-commits {
1001 text-align: center;
1001 text-align: center;
1002 }
1002 }
1003 .load-more-commits:hover {
1003 .load-more-commits:hover {
1004 background-color: @grey7;
1004 background-color: @grey7;
1005 }
1005 }
1006 .load-more-commits {
1006 .load-more-commits {
1007 a {
1007 a {
1008 display: block;
1008 display: block;
1009 }
1009 }
1010 }
1010 }
1011 }
1011 }
1012
1012
1013 #filter_changelog {
1013 #filter_changelog {
1014 float: left;
1014 float: left;
1015 }
1015 }
1016
1016
1017
1017
1018 //--- THEME ------------------//
1018 //--- THEME ------------------//
1019
1019
1020 #logo {
1020 #logo {
1021 float: left;
1021 float: left;
1022 margin: 9px 0 0 0;
1022 margin: 9px 0 0 0;
1023
1023
1024 .header {
1024 .header {
1025 background-color: transparent;
1025 background-color: transparent;
1026 }
1026 }
1027
1027
1028 a {
1028 a {
1029 display: inline-block;
1029 display: inline-block;
1030 }
1030 }
1031
1031
1032 img {
1032 img {
1033 height:30px;
1033 height:30px;
1034 }
1034 }
1035 }
1035 }
1036
1036
1037 .logo-wrapper {
1037 .logo-wrapper {
1038 float:left;
1038 float:left;
1039 }
1039 }
1040
1040
1041 .branding {
1041 .branding {
1042 float: left;
1042 float: left;
1043 padding: 9px 2px;
1043 padding: 9px 2px;
1044 line-height: 1em;
1044 line-height: 1em;
1045 font-size: @navigation-fontsize;
1045 font-size: @navigation-fontsize;
1046
1046
1047 a {
1047 a {
1048 color: @grey5
1048 color: @grey5
1049 }
1049 }
1050 }
1050 }
1051
1051
1052 img {
1052 img {
1053 border: none;
1053 border: none;
1054 outline: none;
1054 outline: none;
1055 }
1055 }
1056 user-profile-header
1056 user-profile-header
1057 label {
1057 label {
1058
1058
1059 input[type="checkbox"] {
1059 input[type="checkbox"] {
1060 margin-right: 1em;
1060 margin-right: 1em;
1061 }
1061 }
1062 input[type="radio"] {
1062 input[type="radio"] {
1063 margin-right: 1em;
1063 margin-right: 1em;
1064 }
1064 }
1065 }
1065 }
1066
1066
1067 .flag_status {
1067 .flag_status {
1068 margin: 2px;
1068 margin: 2px;
1069 &.under_review {
1069 &.under_review {
1070 .circle(5px, @alert3);
1070 .circle(5px, @alert3);
1071 }
1071 }
1072 &.approved {
1072 &.approved {
1073 .circle(5px, @alert1);
1073 .circle(5px, @alert1);
1074 }
1074 }
1075 &.rejected,
1075 &.rejected,
1076 &.forced_closed{
1076 &.forced_closed{
1077 .circle(5px, @alert2);
1077 .circle(5px, @alert2);
1078 }
1078 }
1079 &.not_reviewed {
1079 &.not_reviewed {
1080 .circle(5px, @grey5);
1080 .circle(5px, @grey5);
1081 }
1081 }
1082 }
1082 }
1083
1083
1084 .flag_status_comment_box {
1084 .flag_status_comment_box {
1085 margin: 5px 6px 0px 2px;
1085 margin: 5px 6px 0px 2px;
1086 }
1086 }
1087 .test_pattern_preview {
1087 .test_pattern_preview {
1088 margin: @space 0;
1088 margin: @space 0;
1089
1089
1090 p {
1090 p {
1091 margin-bottom: 0;
1091 margin-bottom: 0;
1092 border-bottom: @border-thickness solid @border-default-color;
1092 border-bottom: @border-thickness solid @border-default-color;
1093 color: @grey3;
1093 color: @grey3;
1094 }
1094 }
1095
1095
1096 .btn {
1096 .btn {
1097 margin-bottom: @padding;
1097 margin-bottom: @padding;
1098 }
1098 }
1099 }
1099 }
1100 #test_pattern_result {
1100 #test_pattern_result {
1101 display: none;
1101 display: none;
1102 &:extend(pre);
1102 &:extend(pre);
1103 padding: .9em;
1103 padding: .9em;
1104 color: @grey3;
1104 color: @grey3;
1105 background-color: @grey7;
1105 background-color: @grey7;
1106 border-right: @border-thickness solid @border-default-color;
1106 border-right: @border-thickness solid @border-default-color;
1107 border-bottom: @border-thickness solid @border-default-color;
1107 border-bottom: @border-thickness solid @border-default-color;
1108 border-left: @border-thickness solid @border-default-color;
1108 border-left: @border-thickness solid @border-default-color;
1109 }
1109 }
1110
1110
1111 #repo_vcs_settings {
1111 #repo_vcs_settings {
1112 #inherit_overlay_vcs_default {
1112 #inherit_overlay_vcs_default {
1113 display: none;
1113 display: none;
1114 }
1114 }
1115 #inherit_overlay_vcs_custom {
1115 #inherit_overlay_vcs_custom {
1116 display: custom;
1116 display: custom;
1117 }
1117 }
1118 &.inherited {
1118 &.inherited {
1119 #inherit_overlay_vcs_default {
1119 #inherit_overlay_vcs_default {
1120 display: block;
1120 display: block;
1121 }
1121 }
1122 #inherit_overlay_vcs_custom {
1122 #inherit_overlay_vcs_custom {
1123 display: none;
1123 display: none;
1124 }
1124 }
1125 }
1125 }
1126 }
1126 }
1127
1127
1128 .issue-tracker-link {
1128 .issue-tracker-link {
1129 color: @rcblue;
1129 color: @rcblue;
1130 }
1130 }
1131
1131
1132 // Issue Tracker Table Show/Hide
1132 // Issue Tracker Table Show/Hide
1133 #repo_issue_tracker {
1133 #repo_issue_tracker {
1134 #inherit_overlay {
1134 #inherit_overlay {
1135 display: none;
1135 display: none;
1136 }
1136 }
1137 #custom_overlay {
1137 #custom_overlay {
1138 display: custom;
1138 display: custom;
1139 }
1139 }
1140 &.inherited {
1140 &.inherited {
1141 #inherit_overlay {
1141 #inherit_overlay {
1142 display: block;
1142 display: block;
1143 }
1143 }
1144 #custom_overlay {
1144 #custom_overlay {
1145 display: none;
1145 display: none;
1146 }
1146 }
1147 }
1147 }
1148 }
1148 }
1149 table.issuetracker {
1149 table.issuetracker {
1150 &.readonly {
1150 &.readonly {
1151 tr, td {
1151 tr, td {
1152 color: @grey3;
1152 color: @grey3;
1153 }
1153 }
1154 }
1154 }
1155 .edit {
1155 .edit {
1156 display: none;
1156 display: none;
1157 }
1157 }
1158 .editopen {
1158 .editopen {
1159 .edit {
1159 .edit {
1160 display: inline;
1160 display: inline;
1161 }
1161 }
1162 .entry {
1162 .entry {
1163 display: none;
1163 display: none;
1164 }
1164 }
1165 }
1165 }
1166 tr td.td-action {
1166 tr td.td-action {
1167 min-width: 117px;
1167 min-width: 117px;
1168 }
1168 }
1169 td input {
1169 td input {
1170 max-width: none;
1170 max-width: none;
1171 min-width: 30px;
1171 min-width: 30px;
1172 width: 80%;
1172 width: 80%;
1173 }
1173 }
1174 .issuetracker_pref input {
1174 .issuetracker_pref input {
1175 width: 40%;
1175 width: 40%;
1176 }
1176 }
1177 input.edit_issuetracker_update {
1177 input.edit_issuetracker_update {
1178 margin-right: 0;
1178 margin-right: 0;
1179 width: auto;
1179 width: auto;
1180 }
1180 }
1181 }
1181 }
1182
1182
1183 table.integrations {
1183 table.integrations {
1184 .td-icon {
1184 .td-icon {
1185 width: 20px;
1185 width: 20px;
1186 .integration-icon {
1186 .integration-icon {
1187 height: 20px;
1187 height: 20px;
1188 width: 20px;
1188 width: 20px;
1189 }
1189 }
1190 }
1190 }
1191 }
1191 }
1192
1192
1193 .integrations {
1193 .integrations {
1194 a.integration-box {
1194 a.integration-box {
1195 color: @text-color;
1195 color: @text-color;
1196 &:hover {
1196 &:hover {
1197 .panel {
1197 .panel {
1198 background: #fbfbfb;
1198 background: #fbfbfb;
1199 }
1199 }
1200 }
1200 }
1201 .integration-icon {
1201 .integration-icon {
1202 width: 30px;
1202 width: 30px;
1203 height: 30px;
1203 height: 30px;
1204 margin-right: 20px;
1204 margin-right: 20px;
1205 float: left;
1205 float: left;
1206 }
1206 }
1207
1207
1208 .panel-body {
1208 .panel-body {
1209 padding: 10px;
1209 padding: 10px;
1210 }
1210 }
1211 .panel {
1211 .panel {
1212 margin-bottom: 10px;
1212 margin-bottom: 10px;
1213 }
1213 }
1214 h2 {
1214 h2 {
1215 display: inline-block;
1215 display: inline-block;
1216 margin: 0;
1216 margin: 0;
1217 min-width: 140px;
1217 min-width: 140px;
1218 }
1218 }
1219 }
1219 }
1220 a.integration-box.dummy-integration {
1220 a.integration-box.dummy-integration {
1221 color: @grey4
1221 color: @grey4
1222 }
1222 }
1223 }
1223 }
1224
1224
1225 //Permissions Settings
1225 //Permissions Settings
1226 #add_perm {
1226 #add_perm {
1227 margin: 0 0 @padding;
1227 margin: 0 0 @padding;
1228 cursor: pointer;
1228 cursor: pointer;
1229 }
1229 }
1230
1230
1231 .perm_ac {
1231 .perm_ac {
1232 input {
1232 input {
1233 width: 95%;
1233 width: 95%;
1234 }
1234 }
1235 }
1235 }
1236
1236
1237 .autocomplete-suggestions {
1237 .autocomplete-suggestions {
1238 width: auto !important; // overrides autocomplete.js
1238 width: auto !important; // overrides autocomplete.js
1239 min-width: 278px;
1239 min-width: 278px;
1240 margin: 0;
1240 margin: 0;
1241 border: @border-thickness solid @grey5;
1241 border: @border-thickness solid @grey5;
1242 border-radius: @border-radius;
1242 border-radius: @border-radius;
1243 color: @grey2;
1243 color: @grey2;
1244 background-color: white;
1244 background-color: white;
1245 }
1245 }
1246
1246
1247 .autocomplete-selected {
1247 .autocomplete-selected {
1248 background: #F0F0F0;
1248 background: #F0F0F0;
1249 }
1249 }
1250
1250
1251 .ac-container-wrap {
1251 .ac-container-wrap {
1252 margin: 0;
1252 margin: 0;
1253 padding: 8px;
1253 padding: 8px;
1254 border-bottom: @border-thickness solid @grey5;
1254 border-bottom: @border-thickness solid @grey5;
1255 list-style-type: none;
1255 list-style-type: none;
1256 cursor: pointer;
1256 cursor: pointer;
1257
1257
1258 &:hover {
1258 &:hover {
1259 background-color: @grey7;
1259 background-color: @grey7;
1260 }
1260 }
1261
1261
1262 img {
1262 img {
1263 height: @gravatar-size;
1263 height: @gravatar-size;
1264 width: @gravatar-size;
1264 width: @gravatar-size;
1265 margin-right: 1em;
1265 margin-right: 1em;
1266 }
1266 }
1267
1267
1268 strong {
1268 strong {
1269 font-weight: normal;
1269 font-weight: normal;
1270 }
1270 }
1271 }
1271 }
1272
1272
1273 // Settings Dropdown
1273 // Settings Dropdown
1274 .user-menu .container {
1274 .user-menu .container {
1275 padding: 0 4px;
1275 padding: 0 4px;
1276 margin: 0;
1276 margin: 0;
1277 }
1277 }
1278
1278
1279 .user-menu .gravatar {
1279 .user-menu .gravatar {
1280 cursor: pointer;
1280 cursor: pointer;
1281 }
1281 }
1282
1282
1283 .codeblock {
1283 .codeblock {
1284 margin-bottom: @padding;
1284 margin-bottom: @padding;
1285 clear: both;
1285 clear: both;
1286
1286
1287 .stats {
1287 .stats {
1288 overflow: hidden;
1288 overflow: hidden;
1289 }
1289 }
1290
1290
1291 .message{
1291 .message{
1292 textarea{
1292 textarea{
1293 margin: 0;
1293 margin: 0;
1294 }
1294 }
1295 }
1295 }
1296
1296
1297 .code-header {
1297 .code-header {
1298 .stats {
1298 .stats {
1299 line-height: 2em;
1299 line-height: 2em;
1300
1300
1301 .revision_id {
1301 .revision_id {
1302 margin-left: 0;
1302 margin-left: 0;
1303 }
1303 }
1304 .buttons {
1304 .buttons {
1305 padding-right: 0;
1305 padding-right: 0;
1306 }
1306 }
1307 }
1307 }
1308
1308
1309 .item{
1309 .item{
1310 margin-right: 0.5em;
1310 margin-right: 0.5em;
1311 }
1311 }
1312 }
1312 }
1313
1313
1314 #editor_container{
1314 #editor_container{
1315 position: relative;
1315 position: relative;
1316 margin: @padding;
1316 margin: @padding;
1317 }
1317 }
1318 }
1318 }
1319
1319
1320 #file_history_container {
1320 #file_history_container {
1321 display: none;
1321 display: none;
1322 }
1322 }
1323
1323
1324 .file-history-inner {
1324 .file-history-inner {
1325 margin-bottom: 10px;
1325 margin-bottom: 10px;
1326 }
1326 }
1327
1327
1328 // Pull Requests
1328 // Pull Requests
1329 .summary-details {
1329 .summary-details {
1330 width: 72%;
1330 width: 72%;
1331 }
1331 }
1332 .pr-summary {
1332 .pr-summary {
1333 border-bottom: @border-thickness solid @grey5;
1333 border-bottom: @border-thickness solid @grey5;
1334 margin-bottom: @space;
1334 margin-bottom: @space;
1335 }
1335 }
1336 .reviewers-title {
1336 .reviewers-title {
1337 width: 25%;
1337 width: 25%;
1338 min-width: 200px;
1338 min-width: 200px;
1339 }
1339 }
1340 .reviewers {
1340 .reviewers {
1341 width: 25%;
1341 width: 25%;
1342 min-width: 200px;
1342 min-width: 200px;
1343 }
1343 }
1344 .reviewers ul li {
1344 .reviewers ul li {
1345 position: relative;
1345 position: relative;
1346 width: 100%;
1346 width: 100%;
1347 padding-bottom: 8px;
1347 padding-bottom: 8px;
1348 list-style-type: none;
1348 list-style-type: none;
1349 }
1349 }
1350
1350
1351 .reviewer_entry {
1351 .reviewer_entry {
1352 min-height: 55px;
1352 min-height: 55px;
1353 }
1353 }
1354
1354
1355 .reviewers_member {
1355 .reviewers_member {
1356 width: 100%;
1356 width: 100%;
1357 overflow: auto;
1357 overflow: auto;
1358 }
1358 }
1359 .reviewer_reason {
1359 .reviewer_reason {
1360 padding-left: 20px;
1360 padding-left: 20px;
1361 line-height: 1.5em;
1361 line-height: 1.5em;
1362 }
1362 }
1363 .reviewer_status {
1363 .reviewer_status {
1364 display: inline-block;
1364 display: inline-block;
1365 vertical-align: top;
1365 vertical-align: top;
1366 width: 25px;
1366 width: 25px;
1367 min-width: 25px;
1367 min-width: 25px;
1368 height: 1.2em;
1368 height: 1.2em;
1369 margin-top: 3px;
1369 margin-top: 3px;
1370 line-height: 1em;
1370 line-height: 1em;
1371 }
1371 }
1372
1372
1373 .reviewer_name {
1373 .reviewer_name {
1374 display: inline-block;
1374 display: inline-block;
1375 max-width: 83%;
1375 max-width: 83%;
1376 padding-right: 20px;
1376 padding-right: 20px;
1377 vertical-align: middle;
1377 vertical-align: middle;
1378 line-height: 1;
1378 line-height: 1;
1379
1379
1380 .rc-user {
1380 .rc-user {
1381 min-width: 0;
1381 min-width: 0;
1382 margin: -2px 1em 0 0;
1382 margin: -2px 1em 0 0;
1383 }
1383 }
1384
1384
1385 .reviewer {
1385 .reviewer {
1386 float: left;
1386 float: left;
1387 }
1387 }
1388 }
1388 }
1389
1389
1390 .reviewer_member_mandatory {
1390 .reviewer_member_mandatory {
1391 position: absolute;
1391 position: absolute;
1392 left: 15px;
1392 left: 15px;
1393 top: 8px;
1393 top: 8px;
1394 width: 16px;
1394 width: 16px;
1395 font-size: 11px;
1395 font-size: 11px;
1396 margin: 0;
1396 margin: 0;
1397 padding: 0;
1397 padding: 0;
1398 color: black;
1398 color: black;
1399 }
1399 }
1400
1400
1401 .reviewer_member_mandatory_remove,
1401 .reviewer_member_mandatory_remove,
1402 .reviewer_member_remove {
1402 .reviewer_member_remove {
1403 position: absolute;
1403 position: absolute;
1404 right: 0;
1404 right: 0;
1405 top: 0;
1405 top: 0;
1406 width: 16px;
1406 width: 16px;
1407 margin-bottom: 10px;
1407 margin-bottom: 10px;
1408 padding: 0;
1408 padding: 0;
1409 color: black;
1409 color: black;
1410 }
1410 }
1411
1411
1412 .reviewer_member_mandatory_remove {
1412 .reviewer_member_mandatory_remove {
1413 color: @grey4;
1413 color: @grey4;
1414 }
1414 }
1415
1415
1416 .reviewer_member_status {
1416 .reviewer_member_status {
1417 margin-top: 5px;
1417 margin-top: 5px;
1418 }
1418 }
1419 .pr-summary #summary{
1419 .pr-summary #summary{
1420 width: 100%;
1420 width: 100%;
1421 }
1421 }
1422 .pr-summary .action_button:hover {
1422 .pr-summary .action_button:hover {
1423 border: 0;
1423 border: 0;
1424 cursor: pointer;
1424 cursor: pointer;
1425 }
1425 }
1426 .pr-details-title {
1426 .pr-details-title {
1427 padding-bottom: 8px;
1427 padding-bottom: 8px;
1428 border-bottom: @border-thickness solid @grey5;
1428 border-bottom: @border-thickness solid @grey5;
1429
1429
1430 .action_button.disabled {
1430 .action_button.disabled {
1431 color: @grey4;
1431 color: @grey4;
1432 cursor: inherit;
1432 cursor: inherit;
1433 }
1433 }
1434 .action_button {
1434 .action_button {
1435 color: @rcblue;
1435 color: @rcblue;
1436 }
1436 }
1437 }
1437 }
1438 .pr-details-content {
1438 .pr-details-content {
1439 margin-top: @textmargin;
1439 margin-top: @textmargin;
1440 margin-bottom: @textmargin;
1440 margin-bottom: @textmargin;
1441 }
1441 }
1442
1442
1443 .pr-reviewer-rules {
1443 .pr-reviewer-rules {
1444 padding: 10px 0px 20px 0px;
1444 padding: 10px 0px 20px 0px;
1445 }
1445 }
1446
1446
1447 .group_members {
1447 .group_members {
1448 margin-top: 0;
1448 margin-top: 0;
1449 padding: 0;
1449 padding: 0;
1450 list-style: outside none none;
1450 list-style: outside none none;
1451
1451
1452 img {
1452 img {
1453 height: @gravatar-size;
1453 height: @gravatar-size;
1454 width: @gravatar-size;
1454 width: @gravatar-size;
1455 margin-right: .5em;
1455 margin-right: .5em;
1456 margin-left: 3px;
1456 margin-left: 3px;
1457 }
1457 }
1458
1458
1459 .to-delete {
1459 .to-delete {
1460 .user {
1460 .user {
1461 text-decoration: line-through;
1461 text-decoration: line-through;
1462 }
1462 }
1463 }
1463 }
1464 }
1464 }
1465
1465
1466 .compare_view_commits_title {
1466 .compare_view_commits_title {
1467 .disabled {
1467 .disabled {
1468 cursor: inherit;
1468 cursor: inherit;
1469 &:hover{
1469 &:hover{
1470 background-color: inherit;
1470 background-color: inherit;
1471 color: inherit;
1471 color: inherit;
1472 }
1472 }
1473 }
1473 }
1474 }
1474 }
1475
1475
1476 .subtitle-compare {
1476 .subtitle-compare {
1477 margin: -15px 0px 0px 0px;
1477 margin: -15px 0px 0px 0px;
1478 }
1478 }
1479
1479
1480 .comments-summary-td {
1480 .comments-summary-td {
1481 border-top: 1px dashed @grey5;
1481 border-top: 1px dashed @grey5;
1482 }
1482 }
1483
1483
1484 // new entry in group_members
1484 // new entry in group_members
1485 .td-author-new-entry {
1485 .td-author-new-entry {
1486 background-color: rgba(red(@alert1), green(@alert1), blue(@alert1), 0.3);
1486 background-color: rgba(red(@alert1), green(@alert1), blue(@alert1), 0.3);
1487 }
1487 }
1488
1488
1489 .usergroup_member_remove {
1489 .usergroup_member_remove {
1490 width: 16px;
1490 width: 16px;
1491 margin-bottom: 10px;
1491 margin-bottom: 10px;
1492 padding: 0;
1492 padding: 0;
1493 color: black !important;
1493 color: black !important;
1494 cursor: pointer;
1494 cursor: pointer;
1495 }
1495 }
1496
1496
1497 .reviewer_ac .ac-input {
1497 .reviewer_ac .ac-input {
1498 width: 92%;
1498 width: 92%;
1499 margin-bottom: 1em;
1499 margin-bottom: 1em;
1500 }
1500 }
1501
1501
1502 .compare_view_commits tr{
1502 .compare_view_commits tr{
1503 height: 20px;
1503 height: 20px;
1504 }
1504 }
1505 .compare_view_commits td {
1505 .compare_view_commits td {
1506 vertical-align: top;
1506 vertical-align: top;
1507 padding-top: 10px;
1507 padding-top: 10px;
1508 }
1508 }
1509 .compare_view_commits .author {
1509 .compare_view_commits .author {
1510 margin-left: 5px;
1510 margin-left: 5px;
1511 }
1511 }
1512
1512
1513 .compare_view_commits {
1513 .compare_view_commits {
1514 .color-a {
1514 .color-a {
1515 color: @alert1;
1515 color: @alert1;
1516 }
1516 }
1517
1517
1518 .color-c {
1518 .color-c {
1519 color: @color3;
1519 color: @color3;
1520 }
1520 }
1521
1521
1522 .color-r {
1522 .color-r {
1523 color: @color5;
1523 color: @color5;
1524 }
1524 }
1525
1525
1526 .color-a-bg {
1526 .color-a-bg {
1527 background-color: @alert1;
1527 background-color: @alert1;
1528 }
1528 }
1529
1529
1530 .color-c-bg {
1530 .color-c-bg {
1531 background-color: @alert3;
1531 background-color: @alert3;
1532 }
1532 }
1533
1533
1534 .color-r-bg {
1534 .color-r-bg {
1535 background-color: @alert2;
1535 background-color: @alert2;
1536 }
1536 }
1537
1537
1538 .color-a-border {
1538 .color-a-border {
1539 border: 1px solid @alert1;
1539 border: 1px solid @alert1;
1540 }
1540 }
1541
1541
1542 .color-c-border {
1542 .color-c-border {
1543 border: 1px solid @alert3;
1543 border: 1px solid @alert3;
1544 }
1544 }
1545
1545
1546 .color-r-border {
1546 .color-r-border {
1547 border: 1px solid @alert2;
1547 border: 1px solid @alert2;
1548 }
1548 }
1549
1549
1550 .commit-change-indicator {
1550 .commit-change-indicator {
1551 width: 15px;
1551 width: 15px;
1552 height: 15px;
1552 height: 15px;
1553 position: relative;
1553 position: relative;
1554 left: 15px;
1554 left: 15px;
1555 }
1555 }
1556
1556
1557 .commit-change-content {
1557 .commit-change-content {
1558 text-align: center;
1558 text-align: center;
1559 vertical-align: middle;
1559 vertical-align: middle;
1560 line-height: 15px;
1560 line-height: 15px;
1561 }
1561 }
1562 }
1562 }
1563
1563
1564 .compare_view_filepath {
1564 .compare_view_filepath {
1565 color: @grey1;
1565 color: @grey1;
1566 }
1566 }
1567
1567
1568 .show_more {
1568 .show_more {
1569 display: inline-block;
1569 display: inline-block;
1570 width: 0;
1570 width: 0;
1571 height: 0;
1571 height: 0;
1572 vertical-align: middle;
1572 vertical-align: middle;
1573 content: "";
1573 content: "";
1574 border: 4px solid;
1574 border: 4px solid;
1575 border-right-color: transparent;
1575 border-right-color: transparent;
1576 border-bottom-color: transparent;
1576 border-bottom-color: transparent;
1577 border-left-color: transparent;
1577 border-left-color: transparent;
1578 font-size: 0;
1578 font-size: 0;
1579 }
1579 }
1580
1580
1581 .journal_more .show_more {
1581 .journal_more .show_more {
1582 display: inline;
1582 display: inline;
1583
1583
1584 &:after {
1584 &:after {
1585 content: none;
1585 content: none;
1586 }
1586 }
1587 }
1587 }
1588
1588
1589 .compare_view_commits .collapse_commit:after {
1589 .compare_view_commits .collapse_commit:after {
1590 cursor: pointer;
1590 cursor: pointer;
1591 content: "\00A0\25B4";
1591 content: "\00A0\25B4";
1592 margin-left: -3px;
1592 margin-left: -3px;
1593 font-size: 17px;
1593 font-size: 17px;
1594 color: @grey4;
1594 color: @grey4;
1595 }
1595 }
1596
1596
1597 .diff_links {
1597 .diff_links {
1598 margin-left: 8px;
1598 margin-left: 8px;
1599 }
1599 }
1600
1600
1601 div.ancestor {
1601 div.ancestor {
1602 margin: -30px 0px;
1602 margin: -30px 0px;
1603 }
1603 }
1604
1604
1605 .cs_icon_td input[type="checkbox"] {
1605 .cs_icon_td input[type="checkbox"] {
1606 display: none;
1606 display: none;
1607 }
1607 }
1608
1608
1609 .cs_icon_td .expand_file_icon:after {
1609 .cs_icon_td .expand_file_icon:after {
1610 cursor: pointer;
1610 cursor: pointer;
1611 content: "\00A0\25B6";
1611 content: "\00A0\25B6";
1612 font-size: 12px;
1612 font-size: 12px;
1613 color: @grey4;
1613 color: @grey4;
1614 }
1614 }
1615
1615
1616 .cs_icon_td .collapse_file_icon:after {
1616 .cs_icon_td .collapse_file_icon:after {
1617 cursor: pointer;
1617 cursor: pointer;
1618 content: "\00A0\25BC";
1618 content: "\00A0\25BC";
1619 font-size: 12px;
1619 font-size: 12px;
1620 color: @grey4;
1620 color: @grey4;
1621 }
1621 }
1622
1622
1623 /*new binary
1623 /*new binary
1624 NEW_FILENODE = 1
1624 NEW_FILENODE = 1
1625 DEL_FILENODE = 2
1625 DEL_FILENODE = 2
1626 MOD_FILENODE = 3
1626 MOD_FILENODE = 3
1627 RENAMED_FILENODE = 4
1627 RENAMED_FILENODE = 4
1628 COPIED_FILENODE = 5
1628 COPIED_FILENODE = 5
1629 CHMOD_FILENODE = 6
1629 CHMOD_FILENODE = 6
1630 BIN_FILENODE = 7
1630 BIN_FILENODE = 7
1631 */
1631 */
1632 .cs_files_expand {
1632 .cs_files_expand {
1633 font-size: @basefontsize + 5px;
1633 font-size: @basefontsize + 5px;
1634 line-height: 1.8em;
1634 line-height: 1.8em;
1635 float: right;
1635 float: right;
1636 }
1636 }
1637
1637
1638 .cs_files_expand span{
1638 .cs_files_expand span{
1639 color: @rcblue;
1639 color: @rcblue;
1640 cursor: pointer;
1640 cursor: pointer;
1641 }
1641 }
1642 .cs_files {
1642 .cs_files {
1643 clear: both;
1643 clear: both;
1644 padding-bottom: @padding;
1644 padding-bottom: @padding;
1645
1645
1646 .cur_cs {
1646 .cur_cs {
1647 margin: 10px 2px;
1647 margin: 10px 2px;
1648 font-weight: bold;
1648 font-weight: bold;
1649 }
1649 }
1650
1650
1651 .node {
1651 .node {
1652 float: left;
1652 float: left;
1653 }
1653 }
1654
1654
1655 .changes {
1655 .changes {
1656 float: right;
1656 float: right;
1657 color: white;
1657 color: white;
1658 font-size: @basefontsize - 4px;
1658 font-size: @basefontsize - 4px;
1659 margin-top: 4px;
1659 margin-top: 4px;
1660 opacity: 0.6;
1660 opacity: 0.6;
1661 filter: Alpha(opacity=60); /* IE8 and earlier */
1661 filter: Alpha(opacity=60); /* IE8 and earlier */
1662
1662
1663 .added {
1663 .added {
1664 background-color: @alert1;
1664 background-color: @alert1;
1665 float: left;
1665 float: left;
1666 text-align: center;
1666 text-align: center;
1667 }
1667 }
1668
1668
1669 .deleted {
1669 .deleted {
1670 background-color: @alert2;
1670 background-color: @alert2;
1671 float: left;
1671 float: left;
1672 text-align: center;
1672 text-align: center;
1673 }
1673 }
1674
1674
1675 .bin {
1675 .bin {
1676 background-color: @alert1;
1676 background-color: @alert1;
1677 text-align: center;
1677 text-align: center;
1678 }
1678 }
1679
1679
1680 /*new binary*/
1680 /*new binary*/
1681 .bin.bin1 {
1681 .bin.bin1 {
1682 background-color: @alert1;
1682 background-color: @alert1;
1683 text-align: center;
1683 text-align: center;
1684 }
1684 }
1685
1685
1686 /*deleted binary*/
1686 /*deleted binary*/
1687 .bin.bin2 {
1687 .bin.bin2 {
1688 background-color: @alert2;
1688 background-color: @alert2;
1689 text-align: center;
1689 text-align: center;
1690 }
1690 }
1691
1691
1692 /*mod binary*/
1692 /*mod binary*/
1693 .bin.bin3 {
1693 .bin.bin3 {
1694 background-color: @grey2;
1694 background-color: @grey2;
1695 text-align: center;
1695 text-align: center;
1696 }
1696 }
1697
1697
1698 /*rename file*/
1698 /*rename file*/
1699 .bin.bin4 {
1699 .bin.bin4 {
1700 background-color: @alert4;
1700 background-color: @alert4;
1701 text-align: center;
1701 text-align: center;
1702 }
1702 }
1703
1703
1704 /*copied file*/
1704 /*copied file*/
1705 .bin.bin5 {
1705 .bin.bin5 {
1706 background-color: @alert4;
1706 background-color: @alert4;
1707 text-align: center;
1707 text-align: center;
1708 }
1708 }
1709
1709
1710 /*chmod file*/
1710 /*chmod file*/
1711 .bin.bin6 {
1711 .bin.bin6 {
1712 background-color: @grey2;
1712 background-color: @grey2;
1713 text-align: center;
1713 text-align: center;
1714 }
1714 }
1715 }
1715 }
1716 }
1716 }
1717
1717
1718 .cs_files .cs_added, .cs_files .cs_A,
1718 .cs_files .cs_added, .cs_files .cs_A,
1719 .cs_files .cs_added, .cs_files .cs_M,
1719 .cs_files .cs_added, .cs_files .cs_M,
1720 .cs_files .cs_added, .cs_files .cs_D {
1720 .cs_files .cs_added, .cs_files .cs_D {
1721 height: 16px;
1721 height: 16px;
1722 padding-right: 10px;
1722 padding-right: 10px;
1723 margin-top: 7px;
1723 margin-top: 7px;
1724 text-align: left;
1724 text-align: left;
1725 }
1725 }
1726
1726
1727 .cs_icon_td {
1727 .cs_icon_td {
1728 min-width: 16px;
1728 min-width: 16px;
1729 width: 16px;
1729 width: 16px;
1730 }
1730 }
1731
1731
1732 .pull-request-merge {
1732 .pull-request-merge {
1733 border: 1px solid @grey5;
1733 border: 1px solid @grey5;
1734 padding: 10px 0px 20px;
1734 padding: 10px 0px 20px;
1735 margin-top: 10px;
1735 margin-top: 10px;
1736 margin-bottom: 20px;
1736 margin-bottom: 20px;
1737 }
1737 }
1738
1738
1739 .pull-request-merge ul {
1739 .pull-request-merge ul {
1740 padding: 0px 0px;
1740 padding: 0px 0px;
1741 }
1741 }
1742
1742
1743 .pull-request-merge li {
1743 .pull-request-merge li {
1744 list-style-type: none;
1744 list-style-type: none;
1745 }
1745 }
1746
1746
1747 .pull-request-merge .pull-request-wrap {
1747 .pull-request-merge .pull-request-wrap {
1748 height: auto;
1748 height: auto;
1749 padding: 0px 0px;
1749 padding: 0px 0px;
1750 text-align: right;
1750 text-align: right;
1751 }
1751 }
1752
1752
1753 .pull-request-merge span {
1753 .pull-request-merge span {
1754 margin-right: 5px;
1754 margin-right: 5px;
1755 }
1755 }
1756
1756
1757 .pull-request-merge-actions {
1757 .pull-request-merge-actions {
1758 min-height: 30px;
1758 min-height: 30px;
1759 padding: 0px 0px;
1759 padding: 0px 0px;
1760 }
1760 }
1761
1761
1762 .pull-request-merge-info {
1762 .pull-request-merge-info {
1763 padding: 0px 5px 5px 0px;
1763 padding: 0px 5px 5px 0px;
1764 }
1764 }
1765
1765
1766 .merge-status {
1766 .merge-status {
1767 margin-right: 5px;
1767 margin-right: 5px;
1768 }
1768 }
1769
1769
1770 .merge-message {
1770 .merge-message {
1771 font-size: 1.2em
1771 font-size: 1.2em
1772 }
1772 }
1773
1773
1774 .merge-message.success i,
1774 .merge-message.success i,
1775 .merge-icon.success i {
1775 .merge-icon.success i {
1776 color:@alert1;
1776 color:@alert1;
1777 }
1777 }
1778
1778
1779 .merge-message.warning i,
1779 .merge-message.warning i,
1780 .merge-icon.warning i {
1780 .merge-icon.warning i {
1781 color: @alert3;
1781 color: @alert3;
1782 }
1782 }
1783
1783
1784 .merge-message.error i,
1784 .merge-message.error i,
1785 .merge-icon.error i {
1785 .merge-icon.error i {
1786 color:@alert2;
1786 color:@alert2;
1787 }
1787 }
1788
1788
1789 .pr-versions {
1789 .pr-versions {
1790 font-size: 1.1em;
1790 font-size: 1.1em;
1791
1791
1792 table {
1792 table {
1793 padding: 0px 5px;
1793 padding: 0px 5px;
1794 }
1794 }
1795
1795
1796 td {
1796 td {
1797 line-height: 15px;
1797 line-height: 15px;
1798 }
1798 }
1799
1799
1800 .flag_status {
1800 .flag_status {
1801 margin: 0;
1801 margin: 0;
1802 }
1802 }
1803
1803
1804 .compare-radio-button {
1804 .compare-radio-button {
1805 position: relative;
1805 position: relative;
1806 top: -3px;
1806 top: -3px;
1807 }
1807 }
1808 }
1808 }
1809
1809
1810
1810
1811 #close_pull_request {
1811 #close_pull_request {
1812 margin-right: 0px;
1812 margin-right: 0px;
1813 }
1813 }
1814
1814
1815 .empty_data {
1815 .empty_data {
1816 color: @grey4;
1816 color: @grey4;
1817 }
1817 }
1818
1818
1819 #changeset_compare_view_content {
1819 #changeset_compare_view_content {
1820 clear: both;
1820 clear: both;
1821 width: 100%;
1821 width: 100%;
1822 box-sizing: border-box;
1822 box-sizing: border-box;
1823 .border-radius(@border-radius);
1823 .border-radius(@border-radius);
1824
1824
1825 .help-block {
1825 .help-block {
1826 margin: @padding 0;
1826 margin: @padding 0;
1827 color: @text-color;
1827 color: @text-color;
1828 &.pre-formatting {
1828 &.pre-formatting {
1829 white-space: pre;
1829 white-space: pre;
1830 }
1830 }
1831 }
1831 }
1832
1832
1833 .empty_data {
1833 .empty_data {
1834 margin: @padding 0;
1834 margin: @padding 0;
1835 }
1835 }
1836
1836
1837 .alert {
1837 .alert {
1838 margin-bottom: @space;
1838 margin-bottom: @space;
1839 }
1839 }
1840 }
1840 }
1841
1841
1842 .table_disp {
1842 .table_disp {
1843 .status {
1843 .status {
1844 width: auto;
1844 width: auto;
1845
1845
1846 .flag_status {
1846 .flag_status {
1847 float: left;
1847 float: left;
1848 }
1848 }
1849 }
1849 }
1850 }
1850 }
1851
1851
1852
1852
1853 .creation_in_progress {
1853 .creation_in_progress {
1854 color: @grey4
1854 color: @grey4
1855 }
1855 }
1856
1856
1857 .status_box_menu {
1857 .status_box_menu {
1858 margin: 0;
1858 margin: 0;
1859 }
1859 }
1860
1860
1861 .notification-table{
1861 .notification-table{
1862 margin-bottom: @space;
1862 margin-bottom: @space;
1863 display: table;
1863 display: table;
1864 width: 100%;
1864 width: 100%;
1865
1865
1866 .container{
1866 .container{
1867 display: table-row;
1867 display: table-row;
1868
1868
1869 .notification-header{
1869 .notification-header{
1870 border-bottom: @border-thickness solid @border-default-color;
1870 border-bottom: @border-thickness solid @border-default-color;
1871 }
1871 }
1872
1872
1873 .notification-subject{
1873 .notification-subject{
1874 display: table-cell;
1874 display: table-cell;
1875 }
1875 }
1876 }
1876 }
1877 }
1877 }
1878
1878
1879 // Notifications
1879 // Notifications
1880 .notification-header{
1880 .notification-header{
1881 display: table;
1881 display: table;
1882 width: 100%;
1882 width: 100%;
1883 padding: floor(@basefontsize/2) 0;
1883 padding: floor(@basefontsize/2) 0;
1884 line-height: 1em;
1884 line-height: 1em;
1885
1885
1886 .desc, .delete-notifications, .read-notifications{
1886 .desc, .delete-notifications, .read-notifications{
1887 display: table-cell;
1887 display: table-cell;
1888 text-align: left;
1888 text-align: left;
1889 }
1889 }
1890
1890
1891 .desc{
1891 .desc{
1892 width: 1163px;
1892 width: 1163px;
1893 }
1893 }
1894
1894
1895 .delete-notifications, .read-notifications{
1895 .delete-notifications, .read-notifications{
1896 width: 35px;
1896 width: 35px;
1897 min-width: 35px; //fixes when only one button is displayed
1897 min-width: 35px; //fixes when only one button is displayed
1898 }
1898 }
1899 }
1899 }
1900
1900
1901 .notification-body {
1901 .notification-body {
1902 .markdown-block,
1902 .markdown-block,
1903 .rst-block {
1903 .rst-block {
1904 padding: @padding 0;
1904 padding: @padding 0;
1905 }
1905 }
1906
1906
1907 .notification-subject {
1907 .notification-subject {
1908 padding: @textmargin 0;
1908 padding: @textmargin 0;
1909 border-bottom: @border-thickness solid @border-default-color;
1909 border-bottom: @border-thickness solid @border-default-color;
1910 }
1910 }
1911 }
1911 }
1912
1912
1913
1913
1914 .notifications_buttons{
1914 .notifications_buttons{
1915 float: right;
1915 float: right;
1916 }
1916 }
1917
1917
1918 #notification-status{
1918 #notification-status{
1919 display: inline;
1919 display: inline;
1920 }
1920 }
1921
1921
1922 // Repositories
1922 // Repositories
1923
1923
1924 #summary.fields{
1924 #summary.fields{
1925 display: table;
1925 display: table;
1926
1926
1927 .field{
1927 .field{
1928 display: table-row;
1928 display: table-row;
1929
1929
1930 .label-summary{
1930 .label-summary{
1931 display: table-cell;
1931 display: table-cell;
1932 min-width: @label-summary-minwidth;
1932 min-width: @label-summary-minwidth;
1933 padding-top: @padding/2;
1933 padding-top: @padding/2;
1934 padding-bottom: @padding/2;
1934 padding-bottom: @padding/2;
1935 padding-right: @padding/2;
1935 padding-right: @padding/2;
1936 }
1936 }
1937
1937
1938 .input{
1938 .input{
1939 display: table-cell;
1939 display: table-cell;
1940 padding: @padding/2;
1940 padding: @padding/2;
1941
1941
1942 input{
1942 input{
1943 min-width: 29em;
1943 min-width: 29em;
1944 padding: @padding/4;
1944 padding: @padding/4;
1945 }
1945 }
1946 }
1946 }
1947 .statistics, .downloads{
1947 .statistics, .downloads{
1948 .disabled{
1948 .disabled{
1949 color: @grey4;
1949 color: @grey4;
1950 }
1950 }
1951 }
1951 }
1952 }
1952 }
1953 }
1953 }
1954
1954
1955 #summary{
1955 #summary{
1956 width: 70%;
1956 width: 70%;
1957 }
1957 }
1958
1958
1959
1959
1960 // Journal
1960 // Journal
1961 .journal.title {
1961 .journal.title {
1962 h5 {
1962 h5 {
1963 float: left;
1963 float: left;
1964 margin: 0;
1964 margin: 0;
1965 width: 70%;
1965 width: 70%;
1966 }
1966 }
1967
1967
1968 ul {
1968 ul {
1969 float: right;
1969 float: right;
1970 display: inline-block;
1970 display: inline-block;
1971 margin: 0;
1971 margin: 0;
1972 width: 30%;
1972 width: 30%;
1973 text-align: right;
1973 text-align: right;
1974
1974
1975 li {
1975 li {
1976 display: inline;
1976 display: inline;
1977 font-size: @journal-fontsize;
1977 font-size: @journal-fontsize;
1978 line-height: 1em;
1978 line-height: 1em;
1979
1979
1980 list-style-type: none;
1980 list-style-type: none;
1981 }
1981 }
1982 }
1982 }
1983 }
1983 }
1984
1984
1985 .filterexample {
1985 .filterexample {
1986 position: absolute;
1986 position: absolute;
1987 top: 95px;
1987 top: 95px;
1988 left: @contentpadding;
1988 left: @contentpadding;
1989 color: @rcblue;
1989 color: @rcblue;
1990 font-size: 11px;
1990 font-size: 11px;
1991 font-family: @text-regular;
1991 font-family: @text-regular;
1992 cursor: help;
1992 cursor: help;
1993
1993
1994 &:hover {
1994 &:hover {
1995 color: @rcdarkblue;
1995 color: @rcdarkblue;
1996 }
1996 }
1997
1997
1998 @media (max-width:768px) {
1998 @media (max-width:768px) {
1999 position: relative;
1999 position: relative;
2000 top: auto;
2000 top: auto;
2001 left: auto;
2001 left: auto;
2002 display: block;
2002 display: block;
2003 }
2003 }
2004 }
2004 }
2005
2005
2006
2006
2007 #journal{
2007 #journal{
2008 margin-bottom: @space;
2008 margin-bottom: @space;
2009
2009
2010 .journal_day{
2010 .journal_day{
2011 margin-bottom: @textmargin/2;
2011 margin-bottom: @textmargin/2;
2012 padding-bottom: @textmargin/2;
2012 padding-bottom: @textmargin/2;
2013 font-size: @journal-fontsize;
2013 font-size: @journal-fontsize;
2014 border-bottom: @border-thickness solid @border-default-color;
2014 border-bottom: @border-thickness solid @border-default-color;
2015 }
2015 }
2016
2016
2017 .journal_container{
2017 .journal_container{
2018 margin-bottom: @space;
2018 margin-bottom: @space;
2019
2019
2020 .journal_user{
2020 .journal_user{
2021 display: inline-block;
2021 display: inline-block;
2022 }
2022 }
2023 .journal_action_container{
2023 .journal_action_container{
2024 display: block;
2024 display: block;
2025 margin-top: @textmargin;
2025 margin-top: @textmargin;
2026
2026
2027 div{
2027 div{
2028 display: inline;
2028 display: inline;
2029 }
2029 }
2030
2030
2031 div.journal_action_params{
2031 div.journal_action_params{
2032 display: block;
2032 display: block;
2033 }
2033 }
2034
2034
2035 div.journal_repo:after{
2035 div.journal_repo:after{
2036 content: "\A";
2036 content: "\A";
2037 white-space: pre;
2037 white-space: pre;
2038 }
2038 }
2039
2039
2040 div.date{
2040 div.date{
2041 display: block;
2041 display: block;
2042 margin-bottom: @textmargin;
2042 margin-bottom: @textmargin;
2043 }
2043 }
2044 }
2044 }
2045 }
2045 }
2046 }
2046 }
2047
2047
2048 // Files
2048 // Files
2049 .edit-file-title {
2049 .edit-file-title {
2050 border-bottom: @border-thickness solid @border-default-color;
2050 border-bottom: @border-thickness solid @border-default-color;
2051
2051
2052 .breadcrumbs {
2052 .breadcrumbs {
2053 margin-bottom: 0;
2053 margin-bottom: 0;
2054 }
2054 }
2055 }
2055 }
2056
2056
2057 .edit-file-fieldset {
2057 .edit-file-fieldset {
2058 margin-top: @sidebarpadding;
2058 margin-top: @sidebarpadding;
2059
2059
2060 .fieldset {
2060 .fieldset {
2061 .left-label {
2061 .left-label {
2062 width: 13%;
2062 width: 13%;
2063 }
2063 }
2064 .right-content {
2064 .right-content {
2065 width: 87%;
2065 width: 87%;
2066 max-width: 100%;
2066 max-width: 100%;
2067 }
2067 }
2068 .filename-label {
2068 .filename-label {
2069 margin-top: 13px;
2069 margin-top: 13px;
2070 }
2070 }
2071 .commit-message-label {
2071 .commit-message-label {
2072 margin-top: 4px;
2072 margin-top: 4px;
2073 }
2073 }
2074 .file-upload-input {
2074 .file-upload-input {
2075 input {
2075 input {
2076 display: none;
2076 display: none;
2077 }
2077 }
2078 margin-top: 10px;
2078 margin-top: 10px;
2079 }
2079 }
2080 .file-upload-label {
2080 .file-upload-label {
2081 margin-top: 10px;
2081 margin-top: 10px;
2082 }
2082 }
2083 p {
2083 p {
2084 margin-top: 5px;
2084 margin-top: 5px;
2085 }
2085 }
2086
2086
2087 }
2087 }
2088 .custom-path-link {
2088 .custom-path-link {
2089 margin-left: 5px;
2089 margin-left: 5px;
2090 }
2090 }
2091 #commit {
2091 #commit {
2092 resize: vertical;
2092 resize: vertical;
2093 }
2093 }
2094 }
2094 }
2095
2095
2096 .delete-file-preview {
2096 .delete-file-preview {
2097 max-height: 250px;
2097 max-height: 250px;
2098 }
2098 }
2099
2099
2100 .new-file,
2100 .new-file,
2101 #filter_activate,
2101 #filter_activate,
2102 #filter_deactivate {
2102 #filter_deactivate {
2103 float: right;
2103 float: right;
2104 margin: 0 0 0 10px;
2104 margin: 0 0 0 10px;
2105 }
2105 }
2106
2106
2107 h3.files_location{
2107 h3.files_location{
2108 line-height: 2.4em;
2108 line-height: 2.4em;
2109 }
2109 }
2110
2110
2111 .browser-nav {
2111 .browser-nav {
2112 width: 100%;
2112 width: 100%;
2113 display: table;
2113 display: table;
2114 margin-bottom: 20px;
2114 margin-bottom: 20px;
2115
2115
2116 .info_box {
2116 .info_box {
2117 float: left;
2117 float: left;
2118 display: inline-table;
2118 display: inline-table;
2119 height: 2.5em;
2119 height: 2.5em;
2120
2120
2121 .browser-cur-rev, .info_box_elem {
2121 .browser-cur-rev, .info_box_elem {
2122 display: table-cell;
2122 display: table-cell;
2123 vertical-align: middle;
2123 vertical-align: middle;
2124 }
2124 }
2125
2125
2126 .drop-menu {
2126 .drop-menu {
2127 margin: 0 10px;
2127 margin: 0 10px;
2128 }
2128 }
2129
2129
2130 .info_box_elem {
2130 .info_box_elem {
2131 border-top: @border-thickness solid @grey5;
2131 border-top: @border-thickness solid @grey5;
2132 border-bottom: @border-thickness solid @grey5;
2132 border-bottom: @border-thickness solid @grey5;
2133 box-shadow: @button-shadow;
2133 box-shadow: @button-shadow;
2134
2134
2135 #at_rev, a {
2135 #at_rev, a {
2136 padding: 0.6em 0.4em;
2136 padding: 0.6em 0.4em;
2137 margin: 0;
2137 margin: 0;
2138 .box-shadow(none);
2138 .box-shadow(none);
2139 border: 0;
2139 border: 0;
2140 height: 12px;
2140 height: 12px;
2141 color: @grey2;
2141 color: @grey2;
2142 }
2142 }
2143
2143
2144 input#at_rev {
2144 input#at_rev {
2145 max-width: 50px;
2145 max-width: 50px;
2146 text-align: center;
2146 text-align: center;
2147 }
2147 }
2148
2148
2149 &.previous {
2149 &.previous {
2150 border: @border-thickness solid @grey5;
2150 border: @border-thickness solid @grey5;
2151 border-top-left-radius: @border-radius;
2151 border-top-left-radius: @border-radius;
2152 border-bottom-left-radius: @border-radius;
2152 border-bottom-left-radius: @border-radius;
2153
2153
2154 &:hover {
2154 &:hover {
2155 border-color: @grey4;
2155 border-color: @grey4;
2156 }
2156 }
2157
2157
2158 .disabled {
2158 .disabled {
2159 color: @grey5;
2159 color: @grey5;
2160 cursor: not-allowed;
2160 cursor: not-allowed;
2161 opacity: 0.5;
2161 opacity: 0.5;
2162 }
2162 }
2163 }
2163 }
2164
2164
2165 &.next {
2165 &.next {
2166 border: @border-thickness solid @grey5;
2166 border: @border-thickness solid @grey5;
2167 border-top-right-radius: @border-radius;
2167 border-top-right-radius: @border-radius;
2168 border-bottom-right-radius: @border-radius;
2168 border-bottom-right-radius: @border-radius;
2169
2169
2170 &:hover {
2170 &:hover {
2171 border-color: @grey4;
2171 border-color: @grey4;
2172 }
2172 }
2173
2173
2174 .disabled {
2174 .disabled {
2175 color: @grey5;
2175 color: @grey5;
2176 cursor: not-allowed;
2176 cursor: not-allowed;
2177 opacity: 0.5;
2177 opacity: 0.5;
2178 }
2178 }
2179 }
2179 }
2180 }
2180 }
2181
2181
2182 .browser-cur-rev {
2182 .browser-cur-rev {
2183
2183
2184 span{
2184 span{
2185 margin: 0;
2185 margin: 0;
2186 color: @rcblue;
2186 color: @rcblue;
2187 height: 12px;
2187 height: 12px;
2188 display: inline-block;
2188 display: inline-block;
2189 padding: 0.7em 1em ;
2189 padding: 0.7em 1em ;
2190 border: @border-thickness solid @rcblue;
2190 border: @border-thickness solid @rcblue;
2191 margin-right: @padding;
2191 margin-right: @padding;
2192 }
2192 }
2193 }
2193 }
2194
2194
2195 .select-index-number {
2196 margin: 0 0 0 20px;
2197 color: @grey3;
2198 }
2199 }
2195 }
2200
2196
2197 .select-index-number {
2198 margin: 0 0 0 20px;
2199 color: @grey3;
2200 }
2201
2201 .search_activate {
2202 .search_activate {
2202 display: table-cell;
2203 display: table-cell;
2203 vertical-align: middle;
2204 vertical-align: middle;
2204
2205
2205 input, label{
2206 input, label{
2206 margin: 0;
2207 margin: 0;
2207 padding: 0;
2208 padding: 0;
2208 }
2209 }
2209
2210
2210 input{
2211 input{
2211 margin-left: @textmargin;
2212 margin-left: @textmargin;
2212 }
2213 }
2213
2214
2214 }
2215 }
2215 }
2216 }
2216
2217
2217 .browser-cur-rev{
2218 .browser-cur-rev{
2218 margin-bottom: @textmargin;
2219 margin-bottom: @textmargin;
2219 }
2220 }
2220
2221
2221 #node_filter_box_loading{
2222 #node_filter_box_loading{
2222 .info_text;
2223 .info_text;
2223 }
2224 }
2224
2225
2225 .browser-search {
2226 .browser-search {
2226 margin: -25px 0px 5px 0px;
2227 margin: -25px 0px 5px 0px;
2227 }
2228 }
2228
2229
2229 .files-quick-filter {
2230 .files-quick-filter {
2230 float: right;
2231 float: right;
2231 width: 180px;
2232 width: 180px;
2232 position: relative;
2233 position: relative;
2233 }
2234 }
2234
2235
2235 .files-filter-box {
2236 .files-filter-box {
2236 display: flex;
2237 display: flex;
2237 padding: 0px;
2238 padding: 0px;
2238 border-radius: 3px;
2239 border-radius: 3px;
2239 margin-bottom: 0;
2240 margin-bottom: 0;
2240
2241
2241 a {
2242 a {
2242 border: none !important;
2243 border: none !important;
2243 }
2244 }
2244
2245
2245 li {
2246 li {
2246 list-style-type: none
2247 list-style-type: none
2247 }
2248 }
2248 }
2249 }
2249
2250
2250 .files-filter-box-path {
2251 .files-filter-box-path {
2251 line-height: 33px;
2252 line-height: 33px;
2252 padding: 0;
2253 padding: 0;
2253 width: 20px;
2254 width: 20px;
2254 position: absolute;
2255 position: absolute;
2255 z-index: 11;
2256 z-index: 11;
2256 left: 5px;
2257 left: 5px;
2257 }
2258 }
2258
2259
2259 .files-filter-box-input {
2260 .files-filter-box-input {
2260 margin-right: 0;
2261 margin-right: 0;
2261
2262
2262 input {
2263 input {
2263 border: 1px solid @white;
2264 border: 1px solid @white;
2264 padding-left: 25px;
2265 padding-left: 25px;
2265 width: 145px;
2266 width: 145px;
2266
2267
2267 &:hover {
2268 &:hover {
2268 border-color: @grey6;
2269 border-color: @grey6;
2269 }
2270 }
2270
2271
2271 &:focus {
2272 &:focus {
2272 border-color: @grey5;
2273 border-color: @grey5;
2273 }
2274 }
2274 }
2275 }
2275 }
2276 }
2276
2277
2277 .browser-result{
2278 .browser-result{
2278 td a{
2279 td a{
2279 margin-left: 0.5em;
2280 margin-left: 0.5em;
2280 display: inline-block;
2281 display: inline-block;
2281
2282
2282 em {
2283 em {
2283 font-weight: @text-bold-weight;
2284 font-weight: @text-bold-weight;
2284 font-family: @text-bold;
2285 font-family: @text-bold;
2285 }
2286 }
2286 }
2287 }
2287 }
2288 }
2288
2289
2289 .browser-highlight{
2290 .browser-highlight{
2290 background-color: @grey5-alpha;
2291 background-color: @grey5-alpha;
2291 }
2292 }
2292
2293
2293
2294
2294 // Search
2295 // Search
2295
2296
2296 .search-form{
2297 .search-form{
2297 #q {
2298 #q {
2298 width: @search-form-width;
2299 width: @search-form-width;
2299 }
2300 }
2300 .fields{
2301 .fields{
2301 margin: 0 0 @space;
2302 margin: 0 0 @space;
2302 }
2303 }
2303
2304
2304 label{
2305 label{
2305 display: inline-block;
2306 display: inline-block;
2306 margin-right: @textmargin;
2307 margin-right: @textmargin;
2307 padding-top: 0.25em;
2308 padding-top: 0.25em;
2308 }
2309 }
2309
2310
2310
2311
2311 .results{
2312 .results{
2312 clear: both;
2313 clear: both;
2313 margin: 0 0 @padding;
2314 margin: 0 0 @padding;
2314 }
2315 }
2315
2316
2316 .search-tags {
2317 .search-tags {
2317 padding: 5px 0;
2318 padding: 5px 0;
2318 }
2319 }
2319 }
2320 }
2320
2321
2321 div.search-feedback-items {
2322 div.search-feedback-items {
2322 display: inline-block;
2323 display: inline-block;
2323 }
2324 }
2324
2325
2325 div.search-code-body {
2326 div.search-code-body {
2326 background-color: #ffffff; padding: 5px 0 5px 10px;
2327 background-color: #ffffff; padding: 5px 0 5px 10px;
2327 pre {
2328 pre {
2328 .match { background-color: #faffa6;}
2329 .match { background-color: #faffa6;}
2329 .break { display: block; width: 100%; background-color: #DDE7EF; color: #747474; }
2330 .break { display: block; width: 100%; background-color: #DDE7EF; color: #747474; }
2330 }
2331 }
2331 }
2332 }
2332
2333
2333 .expand_commit.search {
2334 .expand_commit.search {
2334 .show_more.open {
2335 .show_more.open {
2335 height: auto;
2336 height: auto;
2336 max-height: none;
2337 max-height: none;
2337 }
2338 }
2338 }
2339 }
2339
2340
2340 .search-results {
2341 .search-results {
2341
2342
2342 h2 {
2343 h2 {
2343 margin-bottom: 0;
2344 margin-bottom: 0;
2344 }
2345 }
2345 .codeblock {
2346 .codeblock {
2346 border: none;
2347 border: none;
2347 background: transparent;
2348 background: transparent;
2348 }
2349 }
2349
2350
2350 .codeblock-header {
2351 .codeblock-header {
2351 border: none;
2352 border: none;
2352 background: transparent;
2353 background: transparent;
2353 }
2354 }
2354
2355
2355 .code-body {
2356 .code-body {
2356 border: @border-thickness solid @border-default-color;
2357 border: @border-thickness solid @border-default-color;
2357 .border-radius(@border-radius);
2358 .border-radius(@border-radius);
2358 }
2359 }
2359
2360
2360 .td-commit {
2361 .td-commit {
2361 &:extend(pre);
2362 &:extend(pre);
2362 border-bottom: @border-thickness solid @border-default-color;
2363 border-bottom: @border-thickness solid @border-default-color;
2363 }
2364 }
2364
2365
2365 .message {
2366 .message {
2366 height: auto;
2367 height: auto;
2367 max-width: 350px;
2368 max-width: 350px;
2368 white-space: normal;
2369 white-space: normal;
2369 text-overflow: initial;
2370 text-overflow: initial;
2370 overflow: visible;
2371 overflow: visible;
2371
2372
2372 .match { background-color: #faffa6;}
2373 .match { background-color: #faffa6;}
2373 .break { background-color: #DDE7EF; width: 100%; color: #747474; display: block; }
2374 .break { background-color: #DDE7EF; width: 100%; color: #747474; display: block; }
2374 }
2375 }
2375
2376
2376 }
2377 }
2377
2378
2378 table.rctable td.td-search-results div {
2379 table.rctable td.td-search-results div {
2379 max-width: 100%;
2380 max-width: 100%;
2380 }
2381 }
2381
2382
2382 #tip-box, .tip-box{
2383 #tip-box, .tip-box{
2383 padding: @menupadding/2;
2384 padding: @menupadding/2;
2384 display: block;
2385 display: block;
2385 border: @border-thickness solid @border-highlight-color;
2386 border: @border-thickness solid @border-highlight-color;
2386 .border-radius(@border-radius);
2387 .border-radius(@border-radius);
2387 background-color: white;
2388 background-color: white;
2388 z-index: 99;
2389 z-index: 99;
2389 white-space: pre-wrap;
2390 white-space: pre-wrap;
2390 }
2391 }
2391
2392
2392 #linktt {
2393 #linktt {
2393 width: 79px;
2394 width: 79px;
2394 }
2395 }
2395
2396
2396 #help_kb .modal-content{
2397 #help_kb .modal-content{
2397 max-width: 750px;
2398 max-width: 750px;
2398 margin: 10% auto;
2399 margin: 10% auto;
2399
2400
2400 table{
2401 table{
2401 td,th{
2402 td,th{
2402 border-bottom: none;
2403 border-bottom: none;
2403 line-height: 2.5em;
2404 line-height: 2.5em;
2404 }
2405 }
2405 th{
2406 th{
2406 padding-bottom: @textmargin/2;
2407 padding-bottom: @textmargin/2;
2407 }
2408 }
2408 td.keys{
2409 td.keys{
2409 text-align: center;
2410 text-align: center;
2410 }
2411 }
2411 }
2412 }
2412
2413
2413 .block-left{
2414 .block-left{
2414 width: 45%;
2415 width: 45%;
2415 margin-right: 5%;
2416 margin-right: 5%;
2416 }
2417 }
2417 .modal-footer{
2418 .modal-footer{
2418 clear: both;
2419 clear: both;
2419 }
2420 }
2420 .key.tag{
2421 .key.tag{
2421 padding: 0.5em;
2422 padding: 0.5em;
2422 background-color: @rcblue;
2423 background-color: @rcblue;
2423 color: white;
2424 color: white;
2424 border-color: @rcblue;
2425 border-color: @rcblue;
2425 .box-shadow(none);
2426 .box-shadow(none);
2426 }
2427 }
2427 }
2428 }
2428
2429
2429
2430
2430
2431
2431 //--- IMPORTS FOR REFACTORED STYLES ------------------//
2432 //--- IMPORTS FOR REFACTORED STYLES ------------------//
2432
2433
2433 @import 'statistics-graph';
2434 @import 'statistics-graph';
2434 @import 'tables';
2435 @import 'tables';
2435 @import 'forms';
2436 @import 'forms';
2436 @import 'diff';
2437 @import 'diff';
2437 @import 'summary';
2438 @import 'summary';
2438 @import 'navigation';
2439 @import 'navigation';
2439
2440
2440 //--- SHOW/HIDE SECTIONS --//
2441 //--- SHOW/HIDE SECTIONS --//
2441
2442
2442 .btn-collapse {
2443 .btn-collapse {
2443 float: right;
2444 float: right;
2444 text-align: right;
2445 text-align: right;
2445 font-family: @text-light;
2446 font-family: @text-light;
2446 font-size: @basefontsize;
2447 font-size: @basefontsize;
2447 cursor: pointer;
2448 cursor: pointer;
2448 border: none;
2449 border: none;
2449 color: @rcblue;
2450 color: @rcblue;
2450 }
2451 }
2451
2452
2452 table.rctable,
2453 table.rctable,
2453 table.dataTable {
2454 table.dataTable {
2454 .btn-collapse {
2455 .btn-collapse {
2455 float: right;
2456 float: right;
2456 text-align: right;
2457 text-align: right;
2457 }
2458 }
2458 }
2459 }
2459
2460
2460 table.rctable {
2461 table.rctable {
2461 &.permissions {
2462 &.permissions {
2462
2463
2463 th.td-owner {
2464 th.td-owner {
2464 padding: 0;
2465 padding: 0;
2465 }
2466 }
2466
2467
2467 th {
2468 th {
2468 font-weight: normal;
2469 font-weight: normal;
2469 padding: 0 5px;
2470 padding: 0 5px;
2470 }
2471 }
2471
2472
2472 }
2473 }
2473 }
2474 }
2474
2475
2475
2476
2476 // TODO: johbo: Fix for IE10, this avoids that we see a border
2477 // TODO: johbo: Fix for IE10, this avoids that we see a border
2477 // and padding around checkboxes and radio boxes. Move to the right place,
2478 // and padding around checkboxes and radio boxes. Move to the right place,
2478 // or better: Remove this once we did the form refactoring.
2479 // or better: Remove this once we did the form refactoring.
2479 input[type=checkbox],
2480 input[type=checkbox],
2480 input[type=radio] {
2481 input[type=radio] {
2481 padding: 0;
2482 padding: 0;
2482 border: none;
2483 border: none;
2483 }
2484 }
2484
2485
2485 .toggle-ajax-spinner{
2486 .toggle-ajax-spinner{
2486 height: 16px;
2487 height: 16px;
2487 width: 16px;
2488 width: 16px;
2488 }
2489 }
2489
2490
2490
2491
2491 .markup-form .clearfix {
2492 .markup-form .clearfix {
2492 .border-radius(@border-radius);
2493 .border-radius(@border-radius);
2493 margin: 0px;
2494 margin: 0px;
2494 }
2495 }
2495
2496
2496 .markup-form-area {
2497 .markup-form-area {
2497 padding: 8px 12px;
2498 padding: 8px 12px;
2498 border: 1px solid @grey4;
2499 border: 1px solid @grey4;
2499 .border-radius(@border-radius);
2500 .border-radius(@border-radius);
2500 }
2501 }
2501
2502
2502 .markup-form-area-header .nav-links {
2503 .markup-form-area-header .nav-links {
2503 display: flex;
2504 display: flex;
2504 flex-flow: row wrap;
2505 flex-flow: row wrap;
2505 -webkit-flex-flow: row wrap;
2506 -webkit-flex-flow: row wrap;
2506 width: 100%;
2507 width: 100%;
2507 }
2508 }
2508
2509
2509 .markup-form-area-footer {
2510 .markup-form-area-footer {
2510 display: flex;
2511 display: flex;
2511 }
2512 }
2512
2513
2513 .markup-form-area-footer .toolbar {
2514 .markup-form-area-footer .toolbar {
2514
2515
2515 }
2516 }
2516
2517
2517 // markup Form
2518 // markup Form
2518 div.markup-form {
2519 div.markup-form {
2519 margin-top: 20px;
2520 margin-top: 20px;
2520 }
2521 }
2521
2522
2522 .markup-form strong {
2523 .markup-form strong {
2523 display: block;
2524 display: block;
2524 margin-bottom: 15px;
2525 margin-bottom: 15px;
2525 }
2526 }
2526
2527
2527 .markup-form textarea {
2528 .markup-form textarea {
2528 width: 100%;
2529 width: 100%;
2529 height: 100px;
2530 height: 100px;
2530 font-family: @text-monospace;
2531 font-family: @text-monospace;
2531 }
2532 }
2532
2533
2533 form.markup-form {
2534 form.markup-form {
2534 margin-top: 10px;
2535 margin-top: 10px;
2535 margin-left: 10px;
2536 margin-left: 10px;
2536 }
2537 }
2537
2538
2538 .markup-form .comment-block-ta,
2539 .markup-form .comment-block-ta,
2539 .markup-form .preview-box {
2540 .markup-form .preview-box {
2540 .border-radius(@border-radius);
2541 .border-radius(@border-radius);
2541 .box-sizing(border-box);
2542 .box-sizing(border-box);
2542 background-color: white;
2543 background-color: white;
2543 }
2544 }
2544
2545
2545 .markup-form .preview-box.unloaded {
2546 .markup-form .preview-box.unloaded {
2546 height: 50px;
2547 height: 50px;
2547 text-align: center;
2548 text-align: center;
2548 padding: 20px;
2549 padding: 20px;
2549 background-color: white;
2550 background-color: white;
2550 }
2551 }
2551
2552
2552 .dropzone {
2553 .dropzone {
2553 border: 2px dashed @rcdarkblue;
2554 border: 2px dashed @rcdarkblue;
2554 border-radius: 5px;
2555 border-radius: 5px;
2555 background: white;
2556 background: white;
2556 min-height: 200px;
2557 min-height: 200px;
2557 padding: 54px;
2558 padding: 54px;
2558 }
2559 }
2559 .dropzone .dz-message {
2560 .dropzone .dz-message {
2560 font-weight: 700;
2561 font-weight: 700;
2561 }
2562 }
2562
2563
2563 .dropzone .dz-message {
2564 .dropzone .dz-message {
2564 text-align: center;
2565 text-align: center;
2565 margin: 2em 0;
2566 margin: 2em 0;
2566 }
2567 }
2567
2568
2568 .dz-preview {
2569 .dz-preview {
2569 margin: 10px -40px !important;
2570 margin: 10px -40px !important;
2570 position: relative;
2571 position: relative;
2571 vertical-align: top;
2572 vertical-align: top;
2572 border: 1px solid @grey4;
2573 border: 1px solid @grey4;
2573 border-radius: 5px;
2574 border-radius: 5px;
2574 padding: 10px;
2575 padding: 10px;
2575 }
2576 }
2576
2577
2577 .dz-filename {
2578 .dz-filename {
2578 font-weight: 700;
2579 font-weight: 700;
2579 }
2580 }
2580
2581
2581 .dz-error-message {
2582 .dz-error-message {
2582 color: @alert2;
2583 color: @alert2;
2583 } No newline at end of file
2584 }
@@ -1,273 +1,274 b''
1 @font-face {
1 @font-face {
2 font-family: 'rcicons';
2 font-family: 'rcicons';
3
3
4 src: url('../fonts/RCIcons/rcicons.eot?73199028');
4 src: url('../fonts/RCIcons/rcicons.eot?9641970');
5 src: url('../fonts/RCIcons/rcicons.eot?73199028#iefix') format('embedded-opentype'),
5 src: url('../fonts/RCIcons/rcicons.eot?9641970#iefix') format('embedded-opentype'),
6 url('../fonts/RCIcons/rcicons.woff2?73199028') format('woff2'),
6 url('../fonts/RCIcons/rcicons.woff2?9641970') format('woff2'),
7 url('../fonts/RCIcons/rcicons.woff?73199028') format('woff'),
7 url('../fonts/RCIcons/rcicons.woff?9641970') format('woff'),
8 url('../fonts/RCIconst/rcicons.ttf?73199028') format('truetype'),
8 url('../fonts/RCIcons/rcicons.ttf?9641970') format('truetype'),
9 url('../fonts/RCIcons/rcicons.svg?73199028#rcicons') format('svg');
9 url('../fonts/RCIcons/rcicons.svg?9641970#rcicons') format('svg');
10
10
11 font-weight: normal;
11 font-weight: normal;
12 font-style: normal;
12 font-style: normal;
13 }
13 }
14 /* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */
14 /* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */
15 /* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */
15 /* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */
16 /*
16 /*
17 @media screen and (-webkit-min-device-pixel-ratio:0) {
17 @media screen and (-webkit-min-device-pixel-ratio:0) {
18 @font-face {
18 @font-face {
19 font-family: 'rcicons';
19 font-family: 'rcicons';
20 src: url('../fonts/RCIcons/rcicons.svg?74666722#rcicons') format('svg');
20 src: url('../fonts/RCIcons/rcicons.svg?74666722#rcicons') format('svg');
21 }
21 }
22 }
22 }
23 */
23 */
24
24
25 [class^="icon-"]:before, [class*=" icon-"]:before {
25 [class^="icon-"]:before, [class*=" icon-"]:before {
26 font-family: "rcicons";
26 font-family: "rcicons";
27 font-style: normal;
27 font-style: normal;
28 font-weight: normal;
28 font-weight: normal;
29 speak: none;
29 speak: none;
30
30
31 display: inline-block;
31 display: inline-block;
32 text-decoration: inherit;
32 text-decoration: inherit;
33 width: 1em;
33 width: 1em;
34 margin-right: .2em;
34 margin-right: .2em;
35 text-align: center;
35 text-align: center;
36 /* opacity: .8; */
36 /* opacity: .8; */
37
37
38 /* For safety - reset parent styles, that can break glyph codes*/
38 /* For safety - reset parent styles, that can break glyph codes*/
39 font-variant: normal;
39 font-variant: normal;
40 text-transform: none;
40 text-transform: none;
41
41
42 /* fix buttons height, for twitter bootstrap */
42 /* fix buttons height, for twitter bootstrap */
43 line-height: 1em;
43 line-height: 1em;
44
44
45 /* Animation center compensation - margins should be symmetric */
45 /* Animation center compensation - margins should be symmetric */
46 /* remove if not needed */
46 /* remove if not needed */
47 margin-left: .2em;
47 margin-left: .2em;
48
48
49 /* you can be more comfortable with increased icons size */
49 /* you can be more comfortable with increased icons size */
50 /* font-size: 120%; */
50 /* font-size: 120%; */
51
51
52 /* Font smoothing. That was taken from TWBS */
52 /* Font smoothing. That was taken from TWBS */
53 -webkit-font-smoothing: antialiased;
53 -webkit-font-smoothing: antialiased;
54 -moz-osx-font-smoothing: grayscale;
54 -moz-osx-font-smoothing: grayscale;
55
55
56 /* Uncomment for 3D effect */
56 /* Uncomment for 3D effect */
57 /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
57 /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
58 }
58 }
59
59
60 .animate-spin {
60 .animate-spin {
61 -moz-animation: spin 2s infinite linear;
61 -moz-animation: spin 2s infinite linear;
62 -o-animation: spin 2s infinite linear;
62 -o-animation: spin 2s infinite linear;
63 -webkit-animation: spin 2s infinite linear;
63 -webkit-animation: spin 2s infinite linear;
64 animation: spin 2s infinite linear;
64 animation: spin 2s infinite linear;
65 display: inline-block;
65 display: inline-block;
66 }
66 }
67 @-moz-keyframes spin {
67 @-moz-keyframes spin {
68 0% {
68 0% {
69 -moz-transform: rotate(0deg);
69 -moz-transform: rotate(0deg);
70 -o-transform: rotate(0deg);
70 -o-transform: rotate(0deg);
71 -webkit-transform: rotate(0deg);
71 -webkit-transform: rotate(0deg);
72 transform: rotate(0deg);
72 transform: rotate(0deg);
73 }
73 }
74
74
75 100% {
75 100% {
76 -moz-transform: rotate(359deg);
76 -moz-transform: rotate(359deg);
77 -o-transform: rotate(359deg);
77 -o-transform: rotate(359deg);
78 -webkit-transform: rotate(359deg);
78 -webkit-transform: rotate(359deg);
79 transform: rotate(359deg);
79 transform: rotate(359deg);
80 }
80 }
81 }
81 }
82 @-webkit-keyframes spin {
82 @-webkit-keyframes spin {
83 0% {
83 0% {
84 -moz-transform: rotate(0deg);
84 -moz-transform: rotate(0deg);
85 -o-transform: rotate(0deg);
85 -o-transform: rotate(0deg);
86 -webkit-transform: rotate(0deg);
86 -webkit-transform: rotate(0deg);
87 transform: rotate(0deg);
87 transform: rotate(0deg);
88 }
88 }
89
89
90 100% {
90 100% {
91 -moz-transform: rotate(359deg);
91 -moz-transform: rotate(359deg);
92 -o-transform: rotate(359deg);
92 -o-transform: rotate(359deg);
93 -webkit-transform: rotate(359deg);
93 -webkit-transform: rotate(359deg);
94 transform: rotate(359deg);
94 transform: rotate(359deg);
95 }
95 }
96 }
96 }
97 @-o-keyframes spin {
97 @-o-keyframes spin {
98 0% {
98 0% {
99 -moz-transform: rotate(0deg);
99 -moz-transform: rotate(0deg);
100 -o-transform: rotate(0deg);
100 -o-transform: rotate(0deg);
101 -webkit-transform: rotate(0deg);
101 -webkit-transform: rotate(0deg);
102 transform: rotate(0deg);
102 transform: rotate(0deg);
103 }
103 }
104
104
105 100% {
105 100% {
106 -moz-transform: rotate(359deg);
106 -moz-transform: rotate(359deg);
107 -o-transform: rotate(359deg);
107 -o-transform: rotate(359deg);
108 -webkit-transform: rotate(359deg);
108 -webkit-transform: rotate(359deg);
109 transform: rotate(359deg);
109 transform: rotate(359deg);
110 }
110 }
111 }
111 }
112 @-ms-keyframes spin {
112 @-ms-keyframes spin {
113 0% {
113 0% {
114 -moz-transform: rotate(0deg);
114 -moz-transform: rotate(0deg);
115 -o-transform: rotate(0deg);
115 -o-transform: rotate(0deg);
116 -webkit-transform: rotate(0deg);
116 -webkit-transform: rotate(0deg);
117 transform: rotate(0deg);
117 transform: rotate(0deg);
118 }
118 }
119
119
120 100% {
120 100% {
121 -moz-transform: rotate(359deg);
121 -moz-transform: rotate(359deg);
122 -o-transform: rotate(359deg);
122 -o-transform: rotate(359deg);
123 -webkit-transform: rotate(359deg);
123 -webkit-transform: rotate(359deg);
124 transform: rotate(359deg);
124 transform: rotate(359deg);
125 }
125 }
126 }
126 }
127 @keyframes spin {
127 @keyframes spin {
128 0% {
128 0% {
129 -moz-transform: rotate(0deg);
129 -moz-transform: rotate(0deg);
130 -o-transform: rotate(0deg);
130 -o-transform: rotate(0deg);
131 -webkit-transform: rotate(0deg);
131 -webkit-transform: rotate(0deg);
132 transform: rotate(0deg);
132 transform: rotate(0deg);
133 }
133 }
134
134
135 100% {
135 100% {
136 -moz-transform: rotate(359deg);
136 -moz-transform: rotate(359deg);
137 -o-transform: rotate(359deg);
137 -o-transform: rotate(359deg);
138 -webkit-transform: rotate(359deg);
138 -webkit-transform: rotate(359deg);
139 transform: rotate(359deg);
139 transform: rotate(359deg);
140 }
140 }
141 }
141 }
142
142
143
143
144
144
145 .icon-no-margin::before {
145 .icon-no-margin::before {
146 margin: 0;
146 margin: 0;
147
147
148 }
148 }
149 // -- ICON CLASSES -- //
149 // -- ICON CLASSES -- //
150 // sorter = lambda s: '\n'.join(sorted(s.splitlines()))
150 // sorter = lambda s: '\n'.join(sorted(s.splitlines()))
151
151
152 .icon-delete:before { content: '\e800'; } /* '' */
152 .icon-delete:before { content: '\e800'; } /* '' */
153 .icon-ok:before { content: '\e801'; } /* '' */
153 .icon-ok:before { content: '\e801'; } /* '' */
154 .icon-comment:before { content: '\e802'; } /* '' */
154 .icon-comment:before { content: '\e802'; } /* '' */
155 .icon-bookmark:before { content: '\e803'; } /* '' */
155 .icon-bookmark:before { content: '\e803'; } /* '' */
156 .icon-branch:before { content: '\e804'; } /* '' */
156 .icon-branch:before { content: '\e804'; } /* '' */
157 .icon-tag:before { content: '\e805'; } /* '' */
157 .icon-tag:before { content: '\e805'; } /* '' */
158 .icon-lock:before { content: '\e806'; } /* '' */
158 .icon-lock:before { content: '\e806'; } /* '' */
159 .icon-unlock:before { content: '\e807'; } /* '' */
159 .icon-unlock:before { content: '\e807'; } /* '' */
160 .icon-feed:before { content: '\e808'; } /* '' */
160 .icon-feed:before { content: '\e808'; } /* '' */
161 .icon-left:before { content: '\e809'; } /* '' */
161 .icon-left:before { content: '\e809'; } /* '' */
162 .icon-right:before { content: '\e80a'; } /* '' */
162 .icon-right:before { content: '\e80a'; } /* '' */
163 .icon-down:before { content: '\e80b'; } /* '' */
163 .icon-down:before { content: '\e80b'; } /* '' */
164 .icon-folder:before { content: '\e80c'; } /* '' */
164 .icon-folder:before { content: '\e80c'; } /* '' */
165 .icon-folder-open:before { content: '\e80d'; } /* '' */
165 .icon-folder-open:before { content: '\e80d'; } /* '' */
166 .icon-folder-empty:before { content: '\f114'; } /* '' */
166 .icon-folder-empty:before { content: '\f114'; } /* '' */
167 .icon-folder-open-empty:before { content: '\f115'; } /* '' */
167 .icon-folder-open-empty:before { content: '\f115'; } /* '' */
168 .icon-trash-empty:before { content: '\e80e'; } /* '' */
168 .icon-trash-empty:before { content: '\e80e'; } /* '' */
169 .icon-group:before { content: '\e80f'; } /* '' */
169 .icon-group:before { content: '\e80f'; } /* '' */
170 .icon-remove:before { content: '\e810'; } /* '' */
170 .icon-remove:before { content: '\e810'; } /* '' */
171 .icon-fork:before { content: '\e811'; } /* '' */
171 .icon-fork:before { content: '\e811'; } /* '' */
172 .icon-more:before { content: '\e812'; } /* '' */
172 .icon-more:before { content: '\e812'; } /* '' */
173 .icon-search:before { content: '\e813'; } /* '' */
173 .icon-search:before { content: '\e813'; } /* '' */
174 .icon-scissors:before { content: '\e814'; } /* '' */
174 .icon-scissors:before { content: '\e814'; } /* '' */
175 .icon-download:before { content: '\e815'; } /* '' */
175 .icon-download:before { content: '\e815'; } /* '' */
176 .icon-doc:before { content: '\e816'; } /* '' */
176 .icon-doc:before { content: '\e816'; } /* '' */
177 .icon-cog:before { content: '\e817'; } /* '' */
177 .icon-cog:before { content: '\e817'; } /* '' */
178 .icon-cog-alt:before { content: '\e818'; } /* '' */
178 .icon-cog-alt:before { content: '\e818'; } /* '' */
179 .icon-eye:before { content: '\e819'; } /* '' */
179 .icon-eye:before { content: '\e819'; } /* '' */
180 .icon-eye-off:before { content: '\e81a'; } /* '' */
180 .icon-eye-off:before { content: '\e81a'; } /* '' */
181 .icon-cancel-circled2:before { content: '\e81b'; } /* '' */
181 .icon-cancel-circled2:before { content: '\e81b'; } /* '' */
182 .icon-cancel-circled:before { content: '\e81c'; } /* '' */
182 .icon-cancel-circled:before { content: '\e81c'; } /* '' */
183 .icon-plus:before { content: '\e81d'; } /* '' */
183 .icon-plus:before { content: '\e81d'; } /* '' */
184 .icon-plus-circled:before { content: '\e81e'; } /* '' */
184 .icon-plus-circled:before { content: '\e81e'; } /* '' */
185 .icon-minus-circled:before { content: '\e81f'; } /* '' */
185 .icon-minus-circled:before { content: '\e81f'; } /* '' */
186 .icon-minus:before { content: '\e820'; } /* '' */
186 .icon-minus:before { content: '\e820'; } /* '' */
187 .icon-info-circled:before { content: '\e821'; } /* '' */
187 .icon-info-circled:before { content: '\e821'; } /* '' */
188 .icon-upload:before { content: '\e822'; } /* '' */
188 .icon-upload:before { content: '\e822'; } /* '' */
189 .icon-home:before { content: '\e823'; } /* '' */
189 .icon-git:before { content: '\e82a'; } /* '' */
190 .icon-git:before { content: '\e82a'; } /* '' */
190 .icon-hg:before { content: '\e82d'; } /* '' */
191 .icon-hg:before { content: '\e82d'; } /* '' */
191 .icon-svn:before { content: '\e82e'; } /* '' */
192 .icon-svn:before { content: '\e82e'; } /* '' */
192 .icon-comment-add:before { content: '\e82f'; } /* '' */
193 .icon-comment-add:before { content: '\e82f'; } /* '' */
193 .icon-comment-toggle:before { content: '\e830'; } /* '' */
194 .icon-comment-toggle:before { content: '\e830'; } /* '' */
194 .icon-rhodecode:before { content: '\e831'; } /* '' */
195 .icon-rhodecode:before { content: '\e831'; } /* '' */
195 .icon-up:before { content: '\e832'; } /* '' */
196 .icon-up:before { content: '\e832'; } /* '' */
196 .icon-merge:before { content: '\e833'; } /* '' */
197 .icon-merge:before { content: '\e833'; } /* '' */
197 .icon-docs:before { content: '\f0c5'; } /* '' */
198 .icon-docs:before { content: '\f0c5'; } /* '' */
198 .icon-menu:before { content: '\f0c9'; } /* '' */
199 .icon-menu:before { content: '\f0c9'; } /* '' */
199 .icon-paste:before { content: '\f0ea'; } /* '' */
200 .icon-paste:before { content: '\f0ea'; } /* '' */
200 .icon-doc-text:before { content: '\f0f6'; } /* '' */
201 .icon-doc-text:before { content: '\f0f6'; } /* '' */
201 .icon-plus-squared:before { content: '\f0fe'; } /* '' */
202 .icon-plus-squared:before { content: '\f0fe'; } /* '' */
202 .icon-minus-squared:before { content: '\f146'; } /* '' */
203 .icon-minus-squared:before { content: '\f146'; } /* '' */
203 .icon-minus-squared-alt:before { content: '\f147'; } /* '' */
204 .icon-minus-squared-alt:before { content: '\f147'; } /* '' */
204 .icon-doc-inv:before { content: '\f15b'; } /* '' */
205 .icon-doc-inv:before { content: '\f15b'; } /* '' */
205 .icon-doc-text-inv:before { content: '\f15c'; } /* '' */
206 .icon-doc-text-inv:before { content: '\f15c'; } /* '' */
206 .icon-plus-squared-alt:before { content: '\f196'; } /* '' */
207 .icon-plus-squared-alt:before { content: '\f196'; } /* '' */
207 .icon-file-code:before { content: '\f1c9'; } /* '' */
208 .icon-file-code:before { content: '\f1c9'; } /* '' */
208 .icon-sliders:before { content: '\f1de'; } /* '' */
209 .icon-sliders:before { content: '\f1de'; } /* '' */
209 .icon-trash:before { content: '\f1f8'; } /* '' */
210 .icon-trash:before { content: '\f1f8'; } /* '' */
210 .icon-spin-alt:before { content: '\e834'; } /* '' */
211 .icon-spin-alt:before { content: '\e834'; } /* '' */
211 .icon-spin:before { content: '\e838'; } /* '' */
212 .icon-spin:before { content: '\e838'; } /* '' */
212
213
213
214
214 // MERGED ICONS BASED ON CURRENT ONES
215 // MERGED ICONS BASED ON CURRENT ONES
215 .icon-repo-group:before { &:extend(.icon-folder-open:before); }
216 .icon-repo-group:before { &:extend(.icon-folder-open:before); }
216 .icon-repo-private:before { &:extend(.icon-lock:before); }
217 .icon-repo-private:before { &:extend(.icon-lock:before); }
217 .icon-repo-lock:before { &:extend(.icon-lock:before); }
218 .icon-repo-lock:before { &:extend(.icon-lock:before); }
218 .icon-unlock-alt:before { &:extend(.icon-unlock:before); }
219 .icon-unlock-alt:before { &:extend(.icon-unlock:before); }
219 .icon-repo-unlock:before { &:extend(.icon-unlock:before); }
220 .icon-repo-unlock:before { &:extend(.icon-unlock:before); }
220 .icon-repo-public:before { &:extend(.icon-unlock:before); }
221 .icon-repo-public:before { &:extend(.icon-unlock:before); }
221 .icon-rss-sign:before { &:extend(.icon-feed:before); }
222 .icon-rss-sign:before { &:extend(.icon-feed:before); }
222 .icon-code-fork:before { &:extend(.icon-fork:before); }
223 .icon-code-fork:before { &:extend(.icon-fork:before); }
223 .icon-arrow_up:before { &:extend(.icon-up:before); }
224 .icon-arrow_up:before { &:extend(.icon-up:before); }
224 .icon-file:before { &:extend(.icon-file-code:before); }
225 .icon-file:before { &:extend(.icon-file-code:before); }
225 .icon-file-text:before { &:extend(.icon-file-code:before); }
226 .icon-file-text:before { &:extend(.icon-file-code:before); }
226 .icon-directory:before { &:extend(.icon-folder:before); }
227 .icon-directory:before { &:extend(.icon-folder:before); }
227 .icon-more-linked:before { &:extend(.icon-more:before); }
228 .icon-more-linked:before { &:extend(.icon-more:before); }
228 .icon-clipboard:before { &:extend(.icon-docs:before); }
229 .icon-clipboard:before { &:extend(.icon-docs:before); }
229 .icon-copy:before { &:extend(.icon-docs:before); }
230 .icon-copy:before { &:extend(.icon-docs:before); }
230 .icon-true:before { &:extend(.icon-ok:before); }
231 .icon-true:before { &:extend(.icon-ok:before); }
231 .icon-false:before { &:extend(.icon-delete:before); }
232 .icon-false:before { &:extend(.icon-delete:before); }
232 .icon-expand-linked:before { &:extend(.icon-down:before); }
233 .icon-expand-linked:before { &:extend(.icon-down:before); }
233 .icon-pr-merge-fail:before { &:extend(.icon-delete:before); }
234 .icon-pr-merge-fail:before { &:extend(.icon-delete:before); }
234
235
235 // TRANSFORM
236 // TRANSFORM
236
237
237 .icon-merge:before {transform: rotate(180deg);}
238 .icon-merge:before {transform: rotate(180deg);}
238
239
239 // -- END ICON CLASSES -- //
240 // -- END ICON CLASSES -- //
240
241
241
242
242 //--- ICONS STYLING ------------------//
243 //--- ICONS STYLING ------------------//
243
244
244 .icon-git { color: @color4 !important; }
245 .icon-git { color: @color4 !important; }
245 .icon-hg { color: @color8 !important; }
246 .icon-hg { color: @color8 !important; }
246 .icon-svn { color: @color1 !important; }
247 .icon-svn { color: @color1 !important; }
247 .icon-git-inv { color: @color4 !important; }
248 .icon-git-inv { color: @color4 !important; }
248 .icon-hg-inv { color: @color8 !important; }
249 .icon-hg-inv { color: @color8 !important; }
249 .icon-svn-inv { color: @color1 !important; }
250 .icon-svn-inv { color: @color1 !important; }
250 .icon-repo-lock { color: #FF0000; }
251 .icon-repo-lock { color: #FF0000; }
251 .icon-repo-unlock { color: #FF0000; }
252 .icon-repo-unlock { color: #FF0000; }
252 .icon-false { color: @grey5 }
253 .icon-false { color: @grey5 }
253 .icon-expand-linked { cursor: pointer; color: @grey3; font-size: 14px }
254 .icon-expand-linked { cursor: pointer; color: @grey3; font-size: 14px }
254 .icon-more-linked { cursor: pointer; color: @grey3 }
255 .icon-more-linked { cursor: pointer; color: @grey3 }
255
256
256 .repo-switcher-dropdown .select2-result-label {
257 .repo-switcher-dropdown .select2-result-label {
257 .icon-git:before {
258 .icon-git:before {
258 &:extend(.icon-git-transparent:before);
259 &:extend(.icon-git-transparent:before);
259 }
260 }
260 .icon-hg:before {
261 .icon-hg:before {
261 &:extend(.icon-hg-transparent:before);
262 &:extend(.icon-hg-transparent:before);
262 color: @alert4;
263 color: @alert4;
263 }
264 }
264 .icon-svn:before {
265 .icon-svn:before {
265 &:extend(.icon-svn-transparent:before);
266 &:extend(.icon-svn-transparent:before);
266 }
267 }
267 }
268 }
268
269
269 .icon-user-group:before {
270 .icon-user-group:before {
270 &:extend(.icon-group:before);
271 &:extend(.icon-group:before);
271 margin: 0;
272 margin: 0;
272 font-size: 16px;
273 font-size: 16px;
273 }
274 }
@@ -1,478 +1,476 b''
1 // summary.less
1 // summary.less
2 // For use in RhodeCode applications;
2 // For use in RhodeCode applications;
3 // Used for headers and file detail summary screens.
3 // Used for headers and file detail summary screens.
4
4
5 .summary {
5 .summary {
6 clear: both;
6 clear: both;
7 float: none;
7 float: none;
8 position: relative;
8 position: relative;
9 width: 100%;
9 width: 100%;
10 margin: 0;
10 margin: 0;
11 padding: 0;
11 padding: 0;
12 background: #FCFCFC;
12 background: #FCFCFC;
13 border: 1px solid #EAEAEA;
13 border: 1px solid #EAEAEA;
14 border-radius: @border-radius;
14 border-radius: @border-radius;
15 margin-bottom: 20px;
15 margin-bottom: 20px;
16
16
17 .summary-detail-header {
17 .summary-detail-header {
18 display: block;
18 display: block;
19 width: 100%;
19 width: 100%;
20 margin-bottom: 10px;
20 margin-bottom: 10px;
21 padding: 0 0 .5em 0;
21 padding: 0 0 .5em 0;
22 border-bottom: @border-thickness solid @border-default-color;
22 border-bottom: @border-thickness solid @border-default-color;
23
23
24 .breadcrumbs {
24 .breadcrumbs {
25 display: inline;
25 display: inline;
26 margin: 0;
26 margin: 0;
27 padding: 0;
27 padding: 0;
28 }
28 }
29
29
30 h4 {
30 h4 {
31 margin: 0 1em 0 0;
31 margin: 0 1em 0 0;
32 padding: 10px 0 5px 20px;
32 padding: 10px 0 5px 20px;
33 line-height: 1.2em;
33 line-height: 1.2em;
34 font-size: @basefontsize;
34 font-size: @basefontsize;
35 }
35 }
36
36
37 .action_link {
37 .action_link {
38 float: right;
38 float: right;
39 }
39 }
40
40
41 .new-file {
41 .new-file {
42 float: right;
42 float: right;
43 margin-top: -1.5em;
43 margin-top: -1.5em;
44 }
44 }
45 }
45 }
46
46
47 .summary-detail {
47 .summary-detail {
48 float: none;
48 float: none;
49 position: relative;
49 position: relative;
50 width: 100%;
50 width: 100%;
51 margin: 0;
51 margin: 0;
52 padding: 0 0 20px 0;
52 padding: 0 0 20px 0;
53
53
54 .file_diff_buttons {
54 .file_diff_buttons {
55 margin-top: @space;
55 margin-top: @space;
56 }
56 }
57
57
58 // commit message
58 // commit message
59 .commit {
59 .commit {
60 white-space: pre-wrap;
60 white-space: pre-wrap;
61 }
61 }
62
62
63 .left-clone {
63 .left-clone {
64 float: left;
64 float: left;
65 height: 30px;
65 height: 30px;
66 margin: 0;
66 margin: 0;
67 padding: 0;
67 padding: 0;
68 width: 130px;
68 width: 130px;
69 font-weight: @text-semibold-weight;
69 font-weight: @text-semibold-weight;
70 font-family: @text-semibold;
70 font-family: @text-semibold;
71 }
71 }
72 .left-clone select {
72 .left-clone select {
73 width: 130px;
73 width: 130px;
74 margin-right: 0;
74 margin-right: 0;
75 background-color: @grey7;
75 background-color: @grey7;
76 border-color: @grey4;
76 border-color: @grey4;
77 color: #5C5C5C;
77 color: #5C5C5C;
78 border-top-right-radius: 0;
78 border-top-right-radius: 0;
79 border-bottom-right-radius: 0;
79 border-bottom-right-radius: 0;
80 }
80 }
81
81
82 .right-clone {
82 .right-clone {
83 float: left;
83 float: left;
84 width: ~"calc(100% - 170px)";
84 width: ~"calc(100% - 170px)";
85
85
86 .clipboard-action {
86 .clipboard-action {
87 margin-left: -30px;
87 margin-left: -30px;
88 }
88 }
89 }
89 }
90
90
91 .clone_url_input {
91 .clone_url_input {
92 width: ~"calc(100% - 90px)";
92 width: ~"calc(100% - 90px)";
93 padding: 6px 30px 6px 10px;
93 padding: 6px 30px 6px 10px;
94 height: 14px;
94 height: 14px;
95 box-shadow: 0 1px 1px 0 rgba(0,0,0,0.07);
95 box-shadow: 0 1px 1px 0 rgba(0,0,0,0.07);
96 border-top-left-radius: 0;
96 border-top-left-radius: 0;
97 border-bottom-left-radius: 0;
97 border-bottom-left-radius: 0;
98 margin-left: -1px;
98 margin-left: -1px;
99 }
99 }
100
100
101 &.directory {
101 &.directory {
102 margin-bottom: 0;
102 margin-bottom: 0;
103 }
103 }
104
104
105 .desc {
105 .desc {
106 white-space: pre-wrap;
106 white-space: pre-wrap;
107 }
107 }
108 .disabled {
108 .disabled {
109 opacity: .5;
109 opacity: .5;
110 cursor: inherit;
110 cursor: inherit;
111 }
111 }
112 .help-block {
112 .help-block {
113 color: inherit;
113 color: inherit;
114 margin: 0;
114 margin: 0;
115 }
115 }
116 }
116 }
117
117
118 .sidebar-right {
118 .sidebar-right {
119 float: left;
119 float: left;
120 width: 24%;
120 width: 24%;
121 margin: 0;
121 margin: 0;
122 padding: 0;
122 padding: 0;
123
123
124 ul {
124 ul {
125 margin-left: 0;
125 margin-left: 0;
126 padding-left: 0;
126 padding-left: 0;
127
127
128 li {
128 li {
129 list-style-type: none;
129 list-style-type: none;
130 }
130 }
131 }
131 }
132 }
132 }
133
133
134 #clone_by_name, #clone_by_id{
134 #clone_by_name, #clone_by_id{
135 display: inline-block;
135 display: inline-block;
136 margin-left: 0px;
136 margin-left: 0px;
137 }
137 }
138
138
139 .codeblock {
139 .codeblock {
140 border: none;
140 border: none;
141 background-color: transparent;
141 background-color: transparent;
142 }
142 }
143
143
144 .code-body {
144 .code-body {
145 border: @border-thickness solid @border-default-color;
145 border: @border-thickness solid @border-default-color;
146 .border-radius(@border-radius);
146 .border-radius(@border-radius);
147 }
147 }
148
148
149 .btn-collapse {
149 .btn-collapse {
150 clear: both;
150 clear: both;
151 float: none;
151 float: none;
152 background: #F7F7F7;
152 background: #F7F7F7;
153 text-align: center;
153 text-align: center;
154 color: #949494;
154 color: #949494;
155 font-size: 11px;
155 font-size: 11px;
156
156
157 &:hover {
157 &:hover {
158 background: #f1f1f1;
158 background: #f1f1f1;
159 color: #2B2B2D;
159 color: #2B2B2D;
160 }
160 }
161 }
161 }
162 }
162 }
163
163
164 // this is used outside of just the summary
164 // this is used outside of just the summary
165 .fieldset, // similar to form fieldset
165 .fieldset, // similar to form fieldset
166 .summary .sidebar-right-content { // these have to match
166 .summary .sidebar-right-content { // these have to match
167 clear: both;
167 clear: both;
168 float: none;
168 float: none;
169 position: relative;
169 position: relative;
170 display:block;
170 display:block;
171 width: 100%;
171 width: 100%;
172 min-height: 1em;
172 min-height: 1em;
173 margin-bottom: 10px;
173 margin-bottom: 10px;
174 padding: 0;
174 padding: 0;
175 line-height: 1.2em;
175 line-height: 1.2em;
176
176
177 &:after { // clearfix
177 &:after { // clearfix
178 content: "";
178 content: "";
179 clear: both;
179 clear: both;
180 width: 100%;
180 width: 100%;
181 height: 1em;
181 height: 1em;
182 }
182 }
183 }
183 }
184
184
185 .summary .sidebar-right-content {
185 .summary .sidebar-right-content {
186 margin-bottom: 0;
186 margin-bottom: 0;
187
187
188 .rc-user {
188 .rc-user {
189 min-width: 0;
189 min-width: 0;
190 }
190 }
191
191
192 li {
192 li {
193 list-style: none;
193 list-style: none;
194 line-height: normal;
194 line-height: normal;
195 }
195 }
196 }
196 }
197
197
198 .summary {
198 .summary {
199 .fieldset {
199 .fieldset {
200 margin-bottom: 0;
200 margin-bottom: 0;
201 }
201 }
202 }
202 }
203
203
204 .fieldset {
204 .fieldset {
205
205
206 .left-label { // similar to form legend
206 .left-label { // similar to form legend
207 display: block;
207 display: block;
208 margin: 0;
208 margin: 0;
209 padding: 0;
209 padding: 0;
210 font-weight: @text-semibold-weight;
210 font-weight: @text-semibold-weight;
211 font-family: @text-semibold;
211 font-family: @text-semibold;
212 }
212 }
213
213
214 .left-label-summary {
214 .left-label-summary {
215 padding-left: 20px;
215 padding-left: 20px;
216 margin-bottom: 5px;
216 margin-bottom: 5px;
217
217
218 p {
218 p {
219 margin-bottom: 5px;
219 margin-bottom: 5px;
220 color: @grey1;
220 color: @grey1;
221 float: left;
221 float: left;
222 width: 130px;
222 width: 130px;
223
223
224 &.spacing {
224 &.spacing {
225 margin-top: 10px;
225 margin-top: 10px;
226 }
226 }
227 }
227 }
228
228
229 .right-label-summary {
229 .right-label-summary {
230 float: left;
230 float: left;
231 margin-top: 7px;
231 margin-top: 7px;
232 width: ~"calc(100% - 160px)";
232 width: ~"calc(100% - 160px)";
233 }
233 }
234 }
234 }
235
235
236 .left-label-summary-files {
236 .left-label-summary-files {
237 padding-left: 45px;
237 padding-left: 45px;
238 margin-top: 5px;
238 margin-top: 5px;
239
239
240 p {
240 p {
241 margin-bottom: 5px;
241 margin-bottom: 5px;
242 color: @grey1;
242 color: @grey1;
243 float: left;
243 float: left;
244 width: 130px;
244 width: 130px;
245
245
246 &.spacing {
246 &.spacing {
247 margin-top: 10px;
247 margin-top: 10px;
248 }
248 }
249 }
249 }
250
250
251 .right-label-summary {
251 .right-label-summary {
252 float: left;
252 float: left;
253 margin-top: 7px;
253 margin-top: 7px;
254 }
254 }
255 }
255 }
256
256
257 .left-content {
257 .left-content {
258 width: ~"calc(60% - 20px)";
258 width: ~"calc(60% - 20px)";
259 float: left;
259 float: left;
260 margin: 15px 0 15px 20px;
260 margin: 15px 0 15px 20px;
261
261
262 .rc-user {
262 .rc-user {
263 min-width: auto;
263 min-width: auto;
264 max-width: none;
264 max-width: none;
265 min-height: auto;
265 min-height: auto;
266 padding-right: 5px;
266 padding-right: 5px;
267 }
267 }
268
268
269 .left-content-avatar {
269 .left-content-avatar {
270 width: 45px;
270 width: 45px;
271 float: left;
271 float: left;
272 margin-top: 8px;
272 margin-top: 8px;
273 }
273 }
274
274
275 .left-content-message {
275 .left-content-message {
276 float: left;
276 float: left;
277 width: ~"calc(100% - 45px)";
277 width: ~"calc(100% - 45px)";
278 }
278 }
279 }
279 }
280
280
281 .right-content { // similar to form fields
281 .right-content { // similar to form fields
282 float: left;
282 float: left;
283 display: block;
283 display: block;
284 width: ~"calc(40% - 20px)";
284 width: ~"calc(40% - 20px)";
285 text-align: right;
285 text-align: right;
286 margin: 15px 20px 15px 0;
286 margin: 15px 20px 15px 0;
287
287
288 .truncate-wrap,
288 .truncate-wrap,
289 .truncate {
289 .truncate {
290 max-width: 100%;
290 max-width: 100%;
291 width: 100%;
291 width: 100%;
292 }
292 }
293
293
294 .commit-long {
294 .commit-long {
295 overflow-x: auto;
295 overflow-x: auto;
296 }
296 }
297
297
298 .commit-info {
298 .commit-info {
299 margin-top: 7px;
299 margin-top: 7px;
300 }
300 }
301
301
302 .tag, .tagtag, .branchtag, .booktag, .metatag, .perm_tag {
302 .tag, .tagtag, .branchtag, .booktag, .metatag, .perm_tag {
303 background:transparent;
303 background:transparent;
304 border: none;
304 border: none;
305 box-shadow: none;
305 box-shadow: none;
306 margin-left: 10px;
306 margin-left: 10px;
307 font-size: 13px;
307 font-size: 13px;
308 }
308 }
309
309
310 .tag span, .tag i {
310 .tag span, .tag i {
311 color: @grey1;
311 color: @grey1;
312 }
312 }
313 }
313 }
314 .commit {
314 .commit {
315 color: @grey1;
315 color: @grey1;
316 margin-bottom: 5px;
316 margin-bottom: 5px;
317 white-space: pre;
317 white-space: pre;
318 }
318 }
319 .commit.truncate-wrap {
319 .commit.truncate-wrap {
320 overflow:hidden;
320 overflow:hidden;
321 text-overflow: ellipsis;
321 text-overflow: ellipsis;
322 }
322 }
323 .commit-author {
323 .commit-author {
324 color: @grey1;
324 color: @grey1;
325 }
325 }
326 .commit-date {
326 .commit-date {
327 color: @grey4;
327 color: @grey4;
328 }
328 }
329 }
329 }
330
330
331 // expand commit message
331 // expand commit message
332 #message_expand {
332 #message_expand {
333 clear: both;
333 clear: both;
334 display: block;
334 display: block;
335 color: @rcblue;
335 color: @rcblue;
336 cursor: pointer;
336 cursor: pointer;
337 }
337 }
338
338
339 #trimmed_message_box {
339 #trimmed_message_box {
340 max-height: floor(2 * @basefontsize * 1.2); // 2 lines * line-height
340 max-height: floor(2 * @basefontsize * 1.2); // 2 lines * line-height
341 overflow: hidden;
341 overflow: hidden;
342 }
342 }
343
343
344 // show/hide comments button
344 // show/hide comments button
345 .show-inline-comments {
345 .show-inline-comments {
346 display: inline;
346 display: inline;
347 cursor: pointer;
347 cursor: pointer;
348
348
349 .comments-show { display: inline; }
349 .comments-show { display: inline; }
350 .comments-hide { display: none; }
350 .comments-hide { display: none; }
351
351
352 &.comments-visible {
352 &.comments-visible {
353 .comments-show { display: none; }
353 .comments-show { display: none; }
354 .comments-hide { display: inline; }
354 .comments-hide { display: inline; }
355 }
355 }
356 }
356 }
357
357
358 // Quick Start section
358 // Quick Start section
359
359
360 .empty-repo {
360 .empty-repo {
361 border: 1px solid #EAEAEA;
361 border: 1px solid #EAEAEA;
362 border-bottom: 0;
362 border-bottom: 0;
363 border-radius: @border-radius;
363 border-radius: @border-radius;
364 padding: 0 20px;
364 padding: 0 20px;
365 }
365 }
366
366
367 .empty-repo h3, .quick_start p {
367 .empty-repo h3, .quick_start p {
368 margin-bottom: 10px;
368 margin-bottom: 10px;
369 }
369 }
370
370
371 .quick_start pre {
371 .quick_start pre {
372 background: #FCFEFF;
372 background: #FCFEFF;
373 border: 1px solid #CBDBEB;
373 border: 1px solid #CBDBEB;
374 box-shadow: @button-shadow;
374 box-shadow: @button-shadow;
375 padding: 10px 15px;
375 padding: 10px 15px;
376 border-radius: 4px;
376 border-radius: 4px;
377 color: @grey2;
377 color: @grey2;
378 }
378 }
379
379
380 .clear-fix {
380 .clear-fix {
381 clear: both;
381 clear: both;
382 }
382 }
383
383
384 .quick_start {
384 .quick_start {
385 display: block;
385 display: block;
386 position: relative;
386 position: relative;
387 border: 1px solid #EAEAEA;
387 border: 1px solid #EAEAEA;
388 border-top: 0;
388 border-top: 0;
389 border-radius: @border-radius;
389 border-radius: @border-radius;
390 padding: 0 20px;
390 padding: 0 20px;
391
391
392 // adds some space to make copy and paste easier
392 // adds some space to make copy and paste easier
393 .left-label,
393 .left-label,
394 .right-content {
394 .right-content {
395 line-height: 1.6em;
395 line-height: 1.6em;
396 }
396 }
397 }
397 }
398
398
399
399
400 .submodule {
400 .submodule {
401 .summary-detail {
401 .summary-detail {
402 width: 100%;
402 width: 100%;
403
403
404 .btn-collapse {
404 .btn-collapse {
405 display: none;
405 display: none;
406 }
406 }
407 }
407 }
408 }
408 }
409
409
410 .codeblock-header {
410 .codeblock-header {
411 float: left;
411 float: left;
412 display: block;
412 display: block;
413 width: 100%;
413 width: 100%;
414 margin: 0;
414 margin: 0;
415
415
416 .stats {
416 .stats {
417 float: left;
417 float: left;
418 padding: 10px;
418 padding: 10px;
419 }
419 }
420 .stats-filename {
420 .stats-filename {
421 font-size: 120%;
421 font-size: 120%;
422 }
422 }
423 .stats-first-item {
423 .stats-first-item {
424 padding: 0px 0px 0px 3px;
424 padding: 0px 0px 0px 3px;
425 }
425 }
426
426
427 .stats-info {
427 .stats-info {
428 margin-top: 5px;
429 color: @grey4;
428 color: @grey4;
430 }
429 }
431
430
432 .buttons {
431 .buttons {
433 float: right;
432 float: right;
434 text-align: right;
433 text-align: right;
435 color: @grey4;
434 color: @grey4;
436 padding: 10px;
435 padding: 10px;
437 margin-top: 15px;
438 }
436 }
439
437
440 .file-container {
438 .file-container {
441 display: inline-block;
439 display: inline-block;
442 width: 100%;
440 width: 100%;
443 }
441 }
444
442
445 }
443 }
446
444
447 #summary-menu-stats {
445 #summary-menu-stats {
448
446
449 .stats-bullet {
447 .stats-bullet {
450 color: @grey3;
448 color: @grey3;
451 min-width: 3em;
449 min-width: 3em;
452 }
450 }
453
451
454 .repo-size {
452 .repo-size {
455 margin-bottom: .5em;
453 margin-bottom: .5em;
456 }
454 }
457
455
458 }
456 }
459
457
460 .rctable.repo_summary {
458 .rctable.repo_summary {
461 border: 1px solid #eaeaea;
459 border: 1px solid #eaeaea;
462 border-radius: 2px;
460 border-radius: 2px;
463 border-collapse: inherit;
461 border-collapse: inherit;
464 border-bottom: 0;
462 border-bottom: 0;
465
463
466 th {
464 th {
467 background: @grey7;
465 background: @grey7;
468 border-bottom: 0;
466 border-bottom: 0;
469 }
467 }
470
468
471 td {
469 td {
472 border-color: #eaeaea;
470 border-color: #eaeaea;
473 }
471 }
474
472
475 td.td-status {
473 td.td-status {
476 padding: 0 0 0 10px;
474 padding: 0 0 0 10px;
477 }
475 }
478 }
476 }
@@ -1,597 +1,603 b''
1 {
1 {
2 "name": "rcicons",
2 "name": "rcicons",
3 "css_prefix_text": "icon-",
3 "css_prefix_text": "icon-",
4 "css_use_suffix": false,
4 "css_use_suffix": false,
5 "hinting": true,
5 "hinting": true,
6 "units_per_em": 1000,
6 "units_per_em": 1000,
7 "ascent": 850,
7 "ascent": 850,
8 "copyright": "RhodeCode GmbH",
8 "copyright": "RhodeCode GmbH",
9 "glyphs": [
9 "glyphs": [
10 {
10 {
11 "uid": "a5f9b6d4d795603e6e29a5b8007cc139",
11 "uid": "a5f9b6d4d795603e6e29a5b8007cc139",
12 "css": "bookmark",
12 "css": "bookmark",
13 "code": 59395,
13 "code": 59395,
14 "src": "custom_icons",
14 "src": "custom_icons",
15 "selected": true,
15 "selected": true,
16 "svg": {
16 "svg": {
17 "path": "M780 990L520 700C510 690 495 690 485 700L225 995C205 1015 180 1000 180 965V35C175 15 190 0 205 0H795C810 0 825 15 825 35V960C825 995 795 1010 780 990Z",
17 "path": "M780 990L520 700C510 690 495 690 485 700L225 995C205 1015 180 1000 180 965V35C175 15 190 0 205 0H795C810 0 825 15 825 35V960C825 995 795 1010 780 990Z",
18 "width": 1000
18 "width": 1000
19 },
19 },
20 "search": [
20 "search": [
21 "bookmark"
21 "bookmark"
22 ]
22 ]
23 },
23 },
24 {
24 {
25 "uid": "fbc028d3a6a0df72f8f508ff5dfbab72",
25 "uid": "fbc028d3a6a0df72f8f508ff5dfbab72",
26 "css": "tag",
26 "css": "tag",
27 "code": 59397,
27 "code": 59397,
28 "src": "custom_icons",
28 "src": "custom_icons",
29 "selected": true,
29 "selected": true,
30 "svg": {
30 "svg": {
31 "path": "M459.8 62.5L93.8 53.6C75.9 53.6 62.5 67 62.5 84.8L75.9 450.9C75.9 459.8 80.4 464.3 84.8 473.2L549.1 937.5C562.5 950.9 580.4 950.9 593.8 937.5L946.4 584.8C959.8 571.4 959.8 553.6 946.4 540.2L477.7 71.4C473.2 67 464.3 62.5 459.8 62.5ZM357.1 285.7C357.1 321.4 325.9 352.7 290.2 352.7 254.5 352.7 223.2 321.4 223.2 285.7 223.2 250 254.5 218.8 290.2 218.8S357.1 245.5 357.1 285.7Z",
31 "path": "M459.8 62.5L93.8 53.6C75.9 53.6 62.5 67 62.5 84.8L75.9 450.9C75.9 459.8 80.4 464.3 84.8 473.2L549.1 937.5C562.5 950.9 580.4 950.9 593.8 937.5L946.4 584.8C959.8 571.4 959.8 553.6 946.4 540.2L477.7 71.4C473.2 67 464.3 62.5 459.8 62.5ZM357.1 285.7C357.1 321.4 325.9 352.7 290.2 352.7 254.5 352.7 223.2 321.4 223.2 285.7 223.2 250 254.5 218.8 290.2 218.8S357.1 245.5 357.1 285.7Z",
32 "width": 1000
32 "width": 1000
33 },
33 },
34 "search": [
34 "search": [
35 "tag"
35 "tag"
36 ]
36 ]
37 },
37 },
38 {
38 {
39 "uid": "1c67c02366438b324c184ff9e356dca1",
39 "uid": "1c67c02366438b324c184ff9e356dca1",
40 "css": "branch",
40 "css": "branch",
41 "code": 59396,
41 "code": 59396,
42 "src": "custom_icons",
42 "src": "custom_icons",
43 "selected": true,
43 "selected": true,
44 "svg": {
44 "svg": {
45 "path": "M875 250C875 174.1 817 116.1 741.1 116.1S607.1 174.1 607.1 250C607.1 299.1 633.9 339.3 669.6 361.6 651.8 504.5 531.3 544.6 459.8 558V245.5C504.5 223.2 531.3 183 531.3 133.9 531.3 58 473.2 0 397.3 0S263.4 58 263.4 133.9C263.4 183 290.2 227.7 330.4 250V750C290.2 772.3 263.4 817 263.4 866.1 263.4 942 321.4 1000 397.3 1000S531.3 942 531.3 866.1C531.3 817 504.5 772.3 464.3 750V692C526.8 683 629.5 660.7 709.8 580.4 767.9 522.3 799.1 450.9 808 366.1 848.2 343.8 875 299.1 875 250ZM397.3 89.3C424.1 89.3 442 107.1 442 133.9S424.1 178.6 397.3 178.6 352.7 160.7 352.7 133.9 370.5 89.3 397.3 89.3ZM397.3 910.7C370.5 910.7 352.7 892.9 352.7 866.1S370.5 821.4 397.3 821.4 442 839.3 442 866.1 419.6 910.7 397.3 910.7ZM741.1 205.4C767.9 205.4 785.7 223.2 785.7 250S767.9 294.6 741.1 294.6 696.4 276.8 696.4 250 718.8 205.4 741.1 205.4Z",
45 "path": "M875 250C875 174.1 817 116.1 741.1 116.1S607.1 174.1 607.1 250C607.1 299.1 633.9 339.3 669.6 361.6 651.8 504.5 531.3 544.6 459.8 558V245.5C504.5 223.2 531.3 183 531.3 133.9 531.3 58 473.2 0 397.3 0S263.4 58 263.4 133.9C263.4 183 290.2 227.7 330.4 250V750C290.2 772.3 263.4 817 263.4 866.1 263.4 942 321.4 1000 397.3 1000S531.3 942 531.3 866.1C531.3 817 504.5 772.3 464.3 750V692C526.8 683 629.5 660.7 709.8 580.4 767.9 522.3 799.1 450.9 808 366.1 848.2 343.8 875 299.1 875 250ZM397.3 89.3C424.1 89.3 442 107.1 442 133.9S424.1 178.6 397.3 178.6 352.7 160.7 352.7 133.9 370.5 89.3 397.3 89.3ZM397.3 910.7C370.5 910.7 352.7 892.9 352.7 866.1S370.5 821.4 397.3 821.4 442 839.3 442 866.1 419.6 910.7 397.3 910.7ZM741.1 205.4C767.9 205.4 785.7 223.2 785.7 250S767.9 294.6 741.1 294.6 696.4 276.8 696.4 250 718.8 205.4 741.1 205.4Z",
46 "width": 1000
46 "width": 1000
47 },
47 },
48 "search": [
48 "search": [
49 "branch"
49 "branch"
50 ]
50 ]
51 },
51 },
52 {
52 {
53 "uid": "b75f7b47706aebd803ef370082e8e334",
53 "uid": "b75f7b47706aebd803ef370082e8e334",
54 "css": "group",
54 "css": "group",
55 "code": 59407,
55 "code": 59407,
56 "src": "custom_icons",
56 "src": "custom_icons",
57 "selected": true,
57 "selected": true,
58 "svg": {
58 "svg": {
59 "path": "M961.5 630.8V646.2C961.5 650 957.7 657.7 950 657.7H788.5 784.6C769.2 638.5 746.2 619.2 707.7 615.4 673.1 607.7 653.8 600 638.5 592.3 646.2 584.6 657.7 580.8 669.2 576.9 715.4 569.2 726.9 553.8 734.6 542.3 742.3 530.8 742.3 519.2 734.6 503.8 726.9 488.5 703.8 461.5 703.8 423.1 703.8 384.6 703.8 319.2 776.9 319.2H784.6 792.3C865.4 323.1 869.2 384.6 865.4 423.1 865.4 461.5 842.3 492.3 834.6 503.8 826.9 519.2 826.9 530.8 834.6 542.3 842.3 553.8 857.7 569.2 900 576.9 953.8 580.8 961.5 623.1 961.5 630.8 961.5 630.8 961.5 630.8 961.5 630.8ZM253.8 646.2C269.2 630.8 292.3 615.4 323.1 611.5 361.5 603.8 384.6 596.2 396.2 584.6 388.5 576.9 376.9 569.2 361.5 565.4 315.4 557.7 303.8 542.3 296.2 530.8 288.5 519.2 288.5 507.7 296.2 492.3 303.8 476.9 326.9 450 326.9 411.5 326.9 373.1 326.9 307.7 253.8 307.7H246.2 234.6C161.5 311.5 157.7 373.1 161.5 411.5 161.5 450 184.6 480.8 192.3 492.3 200 507.7 200 519.2 192.3 530.8 184.6 542.3 169.2 557.7 126.9 565.4 80.8 573.1 73.1 615.4 73.1 619.2 73.1 619.2 73.1 619.2 73.1 619.2V634.6C73.1 638.5 76.9 646.2 84.6 646.2H246.2 253.8ZM707.7 634.6C634.6 623.1 611.5 600 600 580.8 588.5 561.5 588.5 542.3 600 519.2 611.5 496.2 650 450 653.8 388.5 657.7 326.9 653.8 223.1 534.6 219.2H519.2 503.8C384.6 223.1 380.8 323.1 384.6 384.6 388.5 446.2 423.1 492.3 438.5 515.4 450 538.5 450 557.7 438.5 576.9 426.9 596.2 403.8 619.2 330.8 630.8 257.7 642.3 246.2 711.5 246.2 719.2 246.2 719.2 246.2 719.2 246.2 719.2V742.3C246.2 750 253.8 757.7 261.5 757.7H519.2 776.9C784.6 757.7 792.3 750 792.3 742.3V719.2C792.3 719.2 792.3 719.2 792.3 719.2 788.5 715.4 780.8 646.2 707.7 634.6Z",
59 "path": "M961.5 630.8V646.2C961.5 650 957.7 657.7 950 657.7H788.5 784.6C769.2 638.5 746.2 619.2 707.7 615.4 673.1 607.7 653.8 600 638.5 592.3 646.2 584.6 657.7 580.8 669.2 576.9 715.4 569.2 726.9 553.8 734.6 542.3 742.3 530.8 742.3 519.2 734.6 503.8 726.9 488.5 703.8 461.5 703.8 423.1 703.8 384.6 703.8 319.2 776.9 319.2H784.6 792.3C865.4 323.1 869.2 384.6 865.4 423.1 865.4 461.5 842.3 492.3 834.6 503.8 826.9 519.2 826.9 530.8 834.6 542.3 842.3 553.8 857.7 569.2 900 576.9 953.8 580.8 961.5 623.1 961.5 630.8 961.5 630.8 961.5 630.8 961.5 630.8ZM253.8 646.2C269.2 630.8 292.3 615.4 323.1 611.5 361.5 603.8 384.6 596.2 396.2 584.6 388.5 576.9 376.9 569.2 361.5 565.4 315.4 557.7 303.8 542.3 296.2 530.8 288.5 519.2 288.5 507.7 296.2 492.3 303.8 476.9 326.9 450 326.9 411.5 326.9 373.1 326.9 307.7 253.8 307.7H246.2 234.6C161.5 311.5 157.7 373.1 161.5 411.5 161.5 450 184.6 480.8 192.3 492.3 200 507.7 200 519.2 192.3 530.8 184.6 542.3 169.2 557.7 126.9 565.4 80.8 573.1 73.1 615.4 73.1 619.2 73.1 619.2 73.1 619.2 73.1 619.2V634.6C73.1 638.5 76.9 646.2 84.6 646.2H246.2 253.8ZM707.7 634.6C634.6 623.1 611.5 600 600 580.8 588.5 561.5 588.5 542.3 600 519.2 611.5 496.2 650 450 653.8 388.5 657.7 326.9 653.8 223.1 534.6 219.2H519.2 503.8C384.6 223.1 380.8 323.1 384.6 384.6 388.5 446.2 423.1 492.3 438.5 515.4 450 538.5 450 557.7 438.5 576.9 426.9 596.2 403.8 619.2 330.8 630.8 257.7 642.3 246.2 711.5 246.2 719.2 246.2 719.2 246.2 719.2 246.2 719.2V742.3C246.2 750 253.8 757.7 261.5 757.7H519.2 776.9C784.6 757.7 792.3 750 792.3 742.3V719.2C792.3 719.2 792.3 719.2 792.3 719.2 788.5 715.4 780.8 646.2 707.7 634.6Z",
60 "width": 1000
60 "width": 1000
61 },
61 },
62 "search": [
62 "search": [
63 "group"
63 "group"
64 ]
64 ]
65 },
65 },
66 {
66 {
67 "uid": "7ae0ef039bb0217d9581e44b09448905",
67 "uid": "7ae0ef039bb0217d9581e44b09448905",
68 "css": "fork",
68 "css": "fork",
69 "code": 59409,
69 "code": 59409,
70 "src": "custom_icons",
70 "src": "custom_icons",
71 "selected": true,
71 "selected": true,
72 "svg": {
72 "svg": {
73 "path": "M792.3 196.2C792.3 138.5 746.2 96.2 692.3 96.2 634.6 96.2 592.3 142.3 592.3 196.2 592.3 230.8 611.5 261.5 638.5 280.8 626.9 365.4 569.2 403.8 511.5 423.1 453.8 407.7 396.2 369.2 384.6 280.8 411.5 261.5 430.8 230.8 430.8 196.2 430.8 138.5 384.6 96.2 330.8 96.2S223.1 138.5 223.1 196.2C223.1 234.6 246.2 269.2 276.9 284.6 288.5 392.3 353.8 473.1 457.7 511.5V673.1C426.9 692.3 407.7 723.1 407.7 761.5 407.7 819.2 453.8 861.5 507.7 861.5S607.7 815.4 607.7 761.5C607.7 723.1 588.5 692.3 557.7 673.1V511.5C661.5 473.1 726.9 392.3 738.5 284.6 769.2 265.4 792.3 234.6 792.3 196.2ZM326.9 161.5C346.2 161.5 361.5 176.9 361.5 196.2S346.2 226.9 326.9 226.9 292.3 215.4 292.3 196.2 307.7 161.5 326.9 161.5ZM507.7 796.2C488.5 796.2 473.1 780.8 473.1 761.5S488.5 726.9 507.7 726.9C526.9 726.9 542.3 742.3 542.3 761.5S526.9 796.2 507.7 796.2ZM692.3 161.5C711.5 161.5 726.9 176.9 726.9 196.2S711.5 226.9 692.3 226.9 657.7 211.5 657.7 192.3 673.1 161.5 692.3 161.5Z",
73 "path": "M792.3 196.2C792.3 138.5 746.2 96.2 692.3 96.2 634.6 96.2 592.3 142.3 592.3 196.2 592.3 230.8 611.5 261.5 638.5 280.8 626.9 365.4 569.2 403.8 511.5 423.1 453.8 407.7 396.2 369.2 384.6 280.8 411.5 261.5 430.8 230.8 430.8 196.2 430.8 138.5 384.6 96.2 330.8 96.2S223.1 138.5 223.1 196.2C223.1 234.6 246.2 269.2 276.9 284.6 288.5 392.3 353.8 473.1 457.7 511.5V673.1C426.9 692.3 407.7 723.1 407.7 761.5 407.7 819.2 453.8 861.5 507.7 861.5S607.7 815.4 607.7 761.5C607.7 723.1 588.5 692.3 557.7 673.1V511.5C661.5 473.1 726.9 392.3 738.5 284.6 769.2 265.4 792.3 234.6 792.3 196.2ZM326.9 161.5C346.2 161.5 361.5 176.9 361.5 196.2S346.2 226.9 326.9 226.9 292.3 215.4 292.3 196.2 307.7 161.5 326.9 161.5ZM507.7 796.2C488.5 796.2 473.1 780.8 473.1 761.5S488.5 726.9 507.7 726.9C526.9 726.9 542.3 742.3 542.3 761.5S526.9 796.2 507.7 796.2ZM692.3 161.5C711.5 161.5 726.9 176.9 726.9 196.2S711.5 226.9 692.3 226.9 657.7 211.5 657.7 192.3 673.1 161.5 692.3 161.5Z",
74 "width": 1000
74 "width": 1000
75 },
75 },
76 "search": [
76 "search": [
77 "fork"
77 "fork"
78 ]
78 ]
79 },
79 },
80 {
80 {
81 "uid": "65e66c3e7d74e2c345fb78fadd400d3f",
81 "uid": "65e66c3e7d74e2c345fb78fadd400d3f",
82 "css": "rhodecode",
82 "css": "rhodecode",
83 "code": 59441,
83 "code": 59441,
84 "src": "custom_icons",
84 "src": "custom_icons",
85 "selected": true,
85 "selected": true,
86 "svg": {
86 "svg": {
87 "path": "M174.6 216.8C173.4 220.9 172.2 225 171 229.1 168.1 239.1 165.2 249.1 162.3 259.1 158.7 271.6 155 284.2 151.4 296.7 148 308.4 144.6 320.1 141.2 331.8 139 339.3 136.8 346.8 134.7 354.3 134.4 355.4 134.1 356.5 133.7 357.6 133.7 357.7 133.9 358.2 134 358.3 134.3 359 134.5 359.7 134.8 360.5 137.2 367.3 139.7 374.1 142.1 381 146 392 149.9 403 153.9 414.1 158.3 426.5 162.8 439 167.2 451.4 171.1 462.5 175.1 473.6 179 484.7 181.5 491.7 184 498.6 186.4 505.6 186.8 506.7 187.2 507.7 187.5 508.8 187.8 509.6 188.6 510.4 189 511.1 192.8 516.9 196.5 522.6 200.3 528.4 206.5 537.9 212.7 547.4 219 556.9 226.2 567.9 233.4 578.9 240.6 590 247.3 600.3 254.1 610.6 260.8 620.9 265.6 628.2 270.4 635.6 275.2 642.9 276.4 644.8 277.6 646.6 278.9 648.5 279.2 649 279.5 649.5 279.8 649.8 282.7 652.6 285.5 655.4 288.4 658.2 294.6 664.3 300.9 670.5 307.1 676.6 315.5 684.9 323.9 693.2 332.4 701.4 341.8 710.6 351.2 719.9 360.6 729.1 369.8 738.1 378.9 747.1 388.1 756.1 395.8 763.7 403.6 771.3 411.3 778.9 416.4 783.9 421.5 788.9 426.6 793.9 428.2 795.5 429.8 797.3 431.6 798.6 438.9 803.9 446.1 809.2 453.4 814.5 463.7 822 473.9 829.5 484.2 837 487.6 839.5 491.1 842 494.5 844.5 495.3 845.1 496.1 845.7 496.9 846.3 497.2 846.5 497.2 846.6 497.6 846.4 504.7 842.7 511.8 839.1 518.9 835.4 530.3 829.5 541.7 823.6 553.1 817.7 559.2 814.5 565.4 811.4 571.5 808.2 571.9 808 572.3 807.1 572.6 806.8 573.7 805.4 574.8 804 576 802.5 580.2 797.2 584.3 791.9 588.5 786.7 594.7 778.9 600.8 771.1 607 763.3 614.5 753.8 622 744.3 629.5 734.8 637.7 724.5 645.8 714.1 654 703.8 662.1 693.5 670.3 683.2 678.4 672.9 685.9 663.5 693.3 654 700.8 644.6 706.9 636.9 713 629.2 719.1 621.5 723.2 616.4 727.2 611.2 731.3 606.1 732.7 604.4 734 602.6 735.4 600.9 735.2 600.8 734.8 600.8 734.6 600.7 733.8 600.5 733 600.4 732.2 600.2 729.1 599.6 726 598.9 722.9 598.2 718 597.1 713 596 708.1 594.8 701.5 593.2 694.9 591.5 688.3 589.7 680.2 587.5 672.2 585.2 664.1 582.9 654.7 580.1 645.4 577.2 636.1 574.1 625.6 570.6 615.2 567 604.8 563.3 593.4 559.1 582 554.8 570.8 550.2 558.6 545.3 546.6 540.1 534.6 534.8 521.9 529.1 509.3 523.1 496.8 516.8 483.7 510.2 470.7 503.4 457.9 496.2 444.6 488.7 431.4 480.9 418.5 472.8 405.1 464.4 392 455.6 379.1 446.4 365.9 437 352.9 427.1 340.3 416.9 327.4 406.4 314.8 395.5 302.7 384.2 290.3 372.6 278.3 360.6 266.8 348.1 255.1 335.3 243.8 322.1 233.2 308.4 222.3 294.4 212 279.9 202.4 265 192.5 249.7 183.4 233.9 175 217.8 175 217.4 174.8 217.1 174.6 216.8ZM172.1 214.2C170.7 218.7 169.3 223.3 167.8 227.8 164.5 238.5 161.1 249.2 157.8 259.9 153.9 272.4 150 285 146.1 297.5 143 307.5 139.9 317.4 136.7 327.4 135.9 330.1 135 332.7 134.2 335.4 134 336.1 133.6 336.7 133.8 337.4 135.4 342.2 137 347.1 138.6 351.9 141.9 361.9 145.2 371.8 148.6 381.8 152.7 394.1 156.8 406.5 160.9 418.8 164.9 430.8 168.9 442.8 172.9 454.8 175.9 463.7 178.8 472.6 181.8 481.4 182.6 483.8 183.4 486.2 184.2 488.7 184.4 489.4 184.6 490.1 184.9 490.8 187.2 495 189.5 499.2 191.8 503.4 196.8 512.6 201.9 521.8 206.9 531 213.2 542.4 219.4 553.9 225.7 565.3 231.7 576.2 237.6 587.1 243.6 598 247.8 605.6 251.9 613.2 256.1 620.8 257.3 623 258.2 625.4 259.9 627.2 264.1 631.7 268.3 636.2 272.5 640.7 280.2 648.9 287.9 657.2 295.5 665.4 304.5 675 313.5 684.7 322.4 694.3 330.5 703 338.6 711.7 346.7 720.4 351.8 725.8 356.8 731.3 361.9 736.7 363.5 738.4 365 740 366.6 741.6 372.3 747.3 378 753 383.7 758.7 392.5 767.5 401.2 776.2 410 785 419.1 794.1 428.3 803.3 437.4 812.4 444.2 819.2 451.1 826.1 457.9 832.9 459.6 834.6 461.3 836.3 463 838 463.3 838.3 463.6 838.6 463.8 838.8 463.9 838.9 465.1 838.7 465.3 838.6 475.9 837.2 486.5 835.8 497 834.5 505.6 833.4 514.1 832.3 522.7 831.2 523 831.2 523.7 830.1 523.9 829.9 525.1 828.6 526.3 827.2 527.6 825.9 532.1 820.9 536.7 815.9 541.2 810.9 547.9 803.5 554.6 796.1 561.4 788.7 569.6 779.7 577.7 770.7 585.9 761.8 594.8 752 603.6 742.3 612.5 732.5 621.3 722.8 630.1 713.1 639 703.4 647 694.5 655.1 685.7 663.1 676.8 669.6 669.6 676.2 662.4 682.7 655.2 687 650.5 691.3 645.8 695.6 641 696.6 639.9 697.7 638.7 698.7 637.6 698.9 637.4 699.6 636.9 699.6 636.6 699.6 636.5 696.6 635.7 696.5 635.7 693.5 634.8 690.4 633.9 687.4 633 682.6 631.5 677.8 630 673 628.4 666.6 626.3 660.1 624.1 653.8 621.8 645.9 619 638.1 616.1 630.3 613.1 621.2 609.6 612.1 606 603.1 602.2 592.9 598 582.8 593.6 572.8 589 561.8 584 550.8 578.8 540 573.4 528.3 567.6 516.7 561.6 505.2 555.3 493 548.7 480.9 541.8 469 534.6 456.5 527.1 444.1 519.3 431.9 511.2 419.2 502.8 406.7 494 394.5 484.9 381.8 475.5 369.5 465.8 357.4 455.7 345 445.3 332.8 434.6 321.1 423.4 309.1 412 297.4 400.2 286.2 388 274.7 375.5 263.7 362.6 253.2 349.3 242.5 335.7 232.3 321.7 222.8 307.2 213 292.4 203.9 277.2 195.5 261.7 186.8 246.5 179 230.5 172.1 214.2ZM169.5 204C168.8 207.8 168.1 211.6 167.3 215.4 165.5 224.9 163.7 234.5 161.9 244 159.5 256.5 157.1 269 154.7 281.5 152.3 294.2 149.8 307 147.4 319.7 145.5 329.9 143.5 340.1 141.6 350.3 140.7 355.2 139.7 360.1 138.8 365 138.7 365.7 139.1 366.4 139.3 367 140.2 369.6 141.1 372.2 142 374.8 145.4 384.5 148.7 394.3 152.1 404 156.4 416.4 160.7 428.7 165 441.1 168.8 452.1 172.6 463 176.4 474 178.3 479.5 180.2 485 182.1 490.5 182.3 491.2 182.7 491.8 183 492.4 184.2 494.8 185.4 497.1 186.5 499.5 190.9 508.4 195.4 517.2 199.8 526.1 205.6 537.7 211.4 549.3 217.2 560.9 222.7 571.9 228.2 583 233.8 594 237.4 601.2 241 608.3 244.6 615.5 245.2 616.6 245.7 617.7 246.3 618.8 246.7 619.6 247.6 620.4 248.2 621.1 252.8 626.6 257.4 632.1 262 637.7 269.5 646.7 276.9 655.6 284.4 664.6 292.8 674.7 301.3 684.9 309.7 695 317.2 704 324.8 713.1 332.3 722.1 337 727.8 341.8 733.5 346.5 739.1 347.2 740 347.9 740.8 348.7 741.7 348.9 741.9 349.2 742 349.4 742.2 350.2 742.7 350.9 743.2 351.7 743.7 358.7 748.5 365.8 753.3 372.8 758.1 383.3 765.3 393.9 772.5 404.4 779.7 414.6 786.6 424.7 793.6 434.9 800.5 440.8 804.5 446.7 808.6 452.7 812.6 456.3 815.1 459.5 818.1 462.9 820.8 472.5 828.7 482.1 836.7 491.7 844.6 498.5 850.2 505.4 855.9 512.2 861.5 512.8 862 512.7 861.9 513.3 861.3 514.2 860.3 515.2 859.2 516.1 858.2 520 853.9 524 849.6 527.9 845.3 534 838.6 540.2 831.9 546.3 825.2 554 816.8 561.7 808.3 569.4 799.9 578.1 790.4 586.7 781 595.4 771.5 604.4 761.7 613.3 751.9 622.3 742.1 630.9 732.6 639.6 723.2 648.2 713.7 655.9 705.3 663.6 696.9 671.3 688.5 677.4 681.8 683.5 675.1 689.6 668.4 693.5 664.1 697.4 659.9 701.3 655.6 702.4 654.4 703.5 653.2 704.6 652 704.6 652 704.6 652 704.6 652 704.6 652 704.6 652 704.6 652 704.6 652.1 701.6 651.3 701.5 651.3 698.5 650.5 695.5 649.5 692.6 648.6 687.9 647.1 683.1 645.5 678.4 643.8 672.1 641.6 665.8 639.2 659.5 636.9 651.8 634 644.1 630.9 636.4 627.8 627.5 624.1 618.6 620.3 609.7 616.4 599.7 612 589.8 607.4 580 602.7 569.2 597.5 558.4 592.1 547.7 586.6 536.2 580.6 524.8 574.4 513.4 568 501.4 561.2 489.5 554.2 477.7 546.9 465.3 539.3 453.1 531.4 441.1 523.3 428.6 514.8 416.3 506.1 404.2 497 391.7 487.7 379.5 478 367.5 468 355.2 457.8 343.2 447.2 331.5 436.3 319.6 425.2 308 413.6 296.8 401.7 285.4 389.6 274.5 377.1 264 364.3 253.3 351.2 243.2 337.8 233.6 323.9 223.8 309.8 214.6 295.4 206.1 280.5 197.4 265.4 189.4 249.9 182.1 234 177.7 224.2 173.5 214.2 169.5 204ZM866 183.5C863.9 179.4 861.1 176.2 857.1 174 851.9 171.1 846.2 168.9 840.7 166.5 829.5 161.7 818.2 157.4 806.7 153.4 783.6 145.4 760 138.9 736.3 132.9 711.7 126.7 687.1 120.9 662.3 115.7 637.1 110.4 611.7 105.6 586.3 101.4 561.2 97.2 536 93.1 510.5 91.1 497.8 90.1 485 89.9 472.4 91.3 465.9 92 459.4 93.2 453 94.2 446.6 95.2 440.1 96.2 433.7 97.3 408.2 101.5 382.8 106 357.4 111 332.2 115.9 307.1 121.2 282.1 126.9 257.2 132.5 232.6 139.2 208.4 147.3 196.3 151.4 184.2 155.8 172.3 160.5 166.4 162.8 160.5 165.2 154.6 167.7 151.7 168.9 148.8 170.2 145.8 171.4 143.2 172.5 140.6 173.5 138.1 174.7 134 176.7 130.6 179.7 128.3 183.6 127 185.8 126.2 188.2 125.3 190.6 124.2 193.6 123.1 196.6 122.1 199.6 118.1 211.5 114.9 223.7 112.5 236 107.7 260.4 106 285.4 106.8 310.2 107.2 322.7 108.2 335.3 109.7 347.7 111.2 360.2 112.7 372.8 115.1 385.2 119.8 410.4 126.7 435.1 134.8 459.3 138.9 471.4 143.3 483.5 147.9 495.4 152.2 506.5 157.5 517.3 162.7 528 173 549.2 184.4 569.8 196.6 589.9 208.8 609.9 221.9 629.3 235.7 648.1 249.5 666.8 264.1 685 279.3 702.6 295.3 721.1 311.7 739.2 328.6 756.9 345.6 774.8 363 792.2 381 809 398.9 825.9 417.4 842.2 436.4 857.8 445.6 865.4 454.9 872.8 464.2 880.2 473.6 887.7 483.1 895.1 492 903.2 494.3 905.2 496.5 907.3 498.7 909.5 498.9 909.7 499.7 910.8 500 910.8 500.2 910.8 500.5 910.8 500.7 910.8 501.2 910.8 502 911 502.5 910.8 507.3 907.1 512 903.3 516.8 899.6 526.2 892.1 535.6 884.6 544.9 876.9 563.3 861.7 581.4 846.2 599.2 830.3 616.9 814.5 634.1 798.2 651 781.5 667.9 764.7 684.4 747.5 700.3 729.7 716.3 711.8 731.8 693.4 746.5 674.4 761 655.7 774.8 636.5 787.8 616.8 800.7 597.2 812.8 577 823.8 556.2 835 535.1 845.2 513.5 854.3 491.4 863.4 469.1 871.2 446.3 877.3 423 883.4 399.9 887.8 376.4 890.3 352.7 892.9 328.6 893.4 304.3 892 280 891.8 276.9 891 273.8 890.3 270.7 889.7 267.7 889 264.6 888.4 261.6 887.2 255.7 886 249.9 884.7 244 882.3 233 879.7 222 876.5 211.1 873.4 201.8 870.1 192.5 866 183.5 863.5 178.4 878.8 211.7 866 183.5ZM814.8 393.5C808.1 418.2 799.5 442.5 789.4 466 780 487.9 770 509.6 758.5 530.5 747.4 550.7 735.1 570.3 722 589.3 708.8 608.4 694.7 626.8 680 644.8 664.8 663.4 649 681.5 632.7 699.1 615.9 717.3 598.5 734.9 580.5 752 562.5 769.1 544.1 785.7 525.1 801.6 515.7 809.5 506.1 817.3 496.5 824.9 496.1 825.2 495.2 826.3 494.7 826.3 494 826.3 493.3 826.3 492.6 826.3 492 826.3 491.4 825.5 491 825.1 490.5 824.6 490 824.1 489.5 823.6 488.4 822.6 487.2 821.5 486.1 820.5 481.6 816.6 476.9 813.1 472.2 809.4 469.9 807.6 467.6 805.7 465.3 803.8 463.1 801.9 461 799.8 458.8 797.8 454.2 793.7 449.7 789.6 445.2 785.5 435.9 777 426.6 768.5 417.5 759.8 408.4 751.1 399.5 742.3 390.9 733.2 386.7 728.8 382.7 724.3 378.4 720 374.2 715.8 370 711.5 365.8 707.2 349.1 690 332.9 672.5 317.4 654.3 301.8 636 286.9 617 273.1 597.3 259.2 577.5 246.4 556.9 234.5 535.8 222.8 515 212.1 493.7 202.6 471.8 193.1 449.9 184.8 427.4 177.9 404.6 176.1 398.6 174.4 392.6 173.1 386.5 171.7 380.1 170.6 373.6 169.6 367.1 167.6 354.2 166.3 341.2 165.5 328.2 164.7 315.3 164.3 302.3 164.5 289.3 164.7 276.7 165.9 264.2 167.5 251.7 167.9 248.5 168.3 245.4 168.7 242.2 168.9 240.6 169.1 239.1 169.3 237.5 169.5 235.9 169.6 234.3 169.8 232.7 170.1 230.3 171.1 228.1 171.7 225.7 172 224.5 172.2 223.2 172.2 221.9 172.2 220.8 172.8 220.1 173.6 219.5 174.6 218.8 175.6 218.3 176.5 217.5 177.1 217 177.6 216.6 178.4 216.3 179.2 216 180.1 215.7 180.9 215.3 183.9 214.2 186.8 213 189.8 211.9 195.7 209.7 201.6 207.5 207.6 205.3 231.3 196.7 255.3 189 279.7 182.4 292 179.1 304.3 176.1 316.7 173.5 322.9 172.2 329.1 170.6 335.4 169.3 341.7 167.9 348 166.6 354.3 165.4 379.8 160.4 405.4 156.3 431.1 152.5 444 150.6 457 148.8 470 147 473.2 146.6 476.5 146.1 479.7 145.7 481.3 145.5 482.8 145.3 484.4 145.1 485.7 144.9 487.1 145 488.4 145.1 493.9 145.1 499.5 145.3 504.9 146.3 506.2 146.5 507.4 146.8 508.6 147.1 510.1 147.5 511.5 147.8 513 148 516.1 148.4 519.2 148.9 522.3 149.3 528.6 150.2 534.8 151.1 541.1 152 553.7 153.8 566.4 155.7 579 157.7 604.4 161.7 629.7 166 654.8 171.4 680 176.8 705 183.2 729.7 190.3 742.1 193.9 754.4 197.7 766.6 201.7 772.7 203.7 778.7 205.8 784.7 207.9 787.7 209 790.7 210 793.7 211.1 795.1 211.6 796.6 212.1 798 212.7 798.7 213 799.4 213.2 800.1 213.5 800.8 213.8 801.9 214 802.4 214.5 803.6 215.7 805.3 216.5 806.3 217.9 806.8 218.7 807.1 219.5 807.2 220.5 807.3 221.2 807.2 221.8 807.4 222.5 807.7 223.4 807.9 224.3 808.1 225.2 809.8 231.5 811.2 237.9 812.3 244.4 813.4 250.8 814.1 257.2 814.5 263.6 814.7 266.8 814.8 270 814.9 273.2 814.9 274 814.9 274.7 814.9 275.5 814.9 276.3 815.2 277.1 815.3 277.8 815.7 279.5 816 281.1 816.4 282.8 821.3 306.5 822.7 330.7 820.7 354.8 819.6 367.7 817.6 380.7 814.8 393.5 807.1 421.7 822.5 357.6 814.8 393.5ZM617.6 393.5C616.1 389 614.6 384.5 613.1 379.9 612.9 379.3 612.7 378.7 612.5 378.1 612.4 377.7 612.5 377.1 612.4 376.7 612.3 376.1 612.2 375.5 612.1 374.9 611.8 373.8 611.4 372.8 610.8 371.9 609.7 370.1 608.1 368.5 606.5 367 604.7 365.2 602.4 362.7 599.6 362.7 601.6 360.7 604.3 360 606.5 358.3 607.6 357.4 608.5 356.5 609.7 355.7 610.5 355.2 611.6 354.7 612.1 353.8 612.3 353.4 612.4 352.9 612.4 352.5 612.9 352 613.3 351.5 613.7 350.9 614.4 349.8 614.7 348.6 614.9 347.3 615.1 345.1 615 342.9 615 340.7 615 338.4 615 336.1 615 333.8 615 331.4 615 329 614.4 326.6 613.1 321.5 610 316.8 606.4 313.1 604.7 311.4 603 309.9 601 308.6 598.3 306.9 595.5 305.5 592.7 304.1 589.9 302.7 586.9 301.8 583.8 301.4 581.4 301.1 579 301.1 576.6 301.1 573.9 301.1 571.2 301.1 568.5 301.1 556.2 301.1 543.8 301.1 531.5 301.1 526.9 301.1 522.3 301.1 517.7 301.1 516.9 301.1 516.1 301.1 515.2 301.1 515.1 301.1 515.2 305.3 515.2 305.6 515.2 308.8 515.2 311.9 515.2 315.1 515.2 316.2 515.2 317.3 515.2 318.4 515.2 318.9 515 319.1 515.5 319.1 516.7 319.1 528 319 528 319.2 528 327.2 528 335.2 528 343.2 528 355.8 528 368.3 528 380.9 528 384.6 528 388.3 528 392 528 392.2 528.1 393.4 527.9 393.4 525.4 393.4 522.8 393.4 520.3 393.4 518.9 393.4 517.6 393.4 516.2 393.4 515.9 393.4 515.2 393.2 515.2 393.6 515.2 395.7 515.2 397.8 515.2 400 515.2 401 515.2 414 515.2 414 524.7 414 534.3 414 543.8 414 549.3 414 554.8 414 560.2 414 561.4 414 562.5 414 563.7 414 564 414 563.8 411.1 563.8 410.7 563.8 405.1 563.8 399.6 563.8 394 563.8 393.4 563.9 393.5 563.3 393.5 562 393.5 560.7 393.5 559.3 393.5 557.8 393.5 556.3 393.5 554.8 393.5 554.6 393.5 553.5 393.7 553.5 393.4 553.5 388.4 553.5 383.4 553.5 378.4 553.5 375.6 553.5 372.9 553.5 370.1 553.5 369.4 553.5 368.8 553.5 368.1 553.5 367.7 554.2 367.9 554.5 367.9 557.4 367.9 560.2 367.9 563.1 367.9 565 367.9 566.9 367.9 568.8 367.9 570.1 367.9 571.6 367.7 572.8 368.1 573.9 368.4 574.8 369 575.7 369.7 576.8 370.6 578.3 371.8 578.9 373.1 579.2 373.8 579.2 374.5 579.2 375.3 579.2 376.6 579.6 377.7 580.2 378.9 580.7 380 581.3 381 581.6 382.2 581.7 382.6 581.7 383 581.8 383.4 581.9 384 582 384.6 582.1 385.1 583.1 390.9 584.2 396.6 585.2 402.4 585.6 404.9 586.1 407.3 586.5 409.8 586.6 410.3 586.7 410.8 586.8 411.3 586.8 411.4 587.2 411.4 587.4 411.4 597.8 411.4 608.3 411.4 618.7 411.4 619.2 411.4 619.6 411.4 620.1 411.4 620.2 411.4 620.2 410.7 620.2 410.6 620.2 408.2 620.2 405.7 620.2 403.3 620.2 398.3 620.2 393.3 620.2 388.4 620.2 388.4 620.2 388.4 620.2 388.4 619.3 390.1 618.5 391.8 617.6 393.5ZM592 339.7C592 342 589.2 342.8 587.7 344.1 587.4 344.3 587.1 344.6 586.9 344.8 586.7 344.8 586.4 344.8 586.2 344.9 585.8 345 585.4 345.2 585.1 345.4 584.4 345.9 583.9 346.6 583.2 347 582.1 347.5 580.7 347.3 579.6 347.3 577.9 347.3 576.3 347.3 574.6 347.3 573.9 347.3 573.2 347.3 572.5 347.3 569.5 347.3 566.4 347.3 563.4 347.3 563 347.3 558.8 347.4 558.8 347.2 558.8 337.9 558.8 328.5 558.8 319.2 558.8 319.1 571.7 319.2 573 319.2 577 319.2 581 319.1 584.9 320.1 586.4 320.5 587.8 321 589.2 321.6 590.1 322.1 591 323.2 591.6 324 593.1 325.7 594.1 327.8 594.5 330 594.6 330.7 594.6 331.3 594.6 332 594.3 332.6 594 333.2 593.7 333.9 593.3 334.7 592.9 335.5 592.6 336.3 592.1 337.4 592 338.5 592 339.7ZM722.6 393.5C722.6 384.2 722.6 374.9 722.6 365.6 722.6 357.1 720.9 348 714.6 341.9 707.5 335.1 696.4 333.9 687 334.7 685.1 334.9 683.2 335.3 681.4 336.1 680.4 336.5 679.5 336.9 678.6 337.6 678 338.1 677.3 338.5 676.7 338.8 673.6 340.4 670.5 341.6 668.8 344.9 668.8 335.9 668.8 326.8 668.8 317.8 668.8 311.9 668.8 306 668.8 300.1 668.8 298.4 668.8 296.6 668.8 294.9 668.8 294.4 669.1 293.7 668.5 293.7 657.9 293.7 647.3 293.7 636.7 293.7 635.5 293.7 634.2 293.7 633 293.7 633 293.7 633 297.8 633 298.1 633 303.4 633 308.7 633 314 633 314.3 633.8 314.2 634 314.2 635.4 314.2 636.7 314.2 638.1 314.2 640.6 314.2 643.2 314.2 645.7 314.2 645.9 314.2 645.8 319.4 645.8 319.8 645.8 331.2 645.8 342.6 645.8 353.9 645.8 364.9 645.8 375.8 645.8 386.8 645.8 388 645.8 389.2 645.8 390.3 645.8 391.2 645.7 391 644.6 391 641.6 391 638.7 391 635.7 391 634.8 391 633.9 391 633 391 632.9 391 632.9 391.9 632.9 392 632.9 397.7 632.9 403.4 632.9 409 632.9 409.8 632.9 410.5 632.9 411.3 632.9 411.5 633 411.5 633.2 411.5 634.5 411.5 635.9 411.5 637.2 411.5 649.1 411.5 661 411.5 672.9 411.5 673.4 411.5 681.5 411.5 681.5 411.5 681.5 406.5 681.5 401.5 681.5 396.5 681.5 394.7 681.5 392.9 681.5 391.1 681.5 391.1 675.6 391.1 675.2 391.1 674.8 391.1 668.7 391.1 668.7 391.1 668.7 389.8 668.7 388.5 668.7 387.3 668.7 381.2 668.7 375 668.7 368.9 668.7 366.5 668.7 364.2 668.7 361.8 668.7 361.3 668.7 360.9 668.7 360.4 668.7 360 670.3 358.8 670.6 358.5 671.7 357.5 672.8 356.5 674.2 355.8 674.7 355.5 675.3 355.3 675.8 355.3 676.5 355.2 676.8 354.8 677.4 354.3 678.5 353.5 679.7 353 681 352.8 683.6 352.4 685.8 352.7 687.9 354.2 689.1 355.1 690.1 356.1 691.2 357.2 692 358 692.7 358.8 693.3 359.8 694.2 361.6 694.3 363.7 694.3 365.7 694.4 369.3 694.3 372.9 694.3 376.6 694.3 387.8 694.3 399 694.3 410.3 694.3 410.9 694 411.6 694.7 411.6 696.4 411.6 698.1 411.6 699.8 411.6 706 411.6 712.3 411.6 718.5 411.6 722.4 411.6 726.3 411.6 730.2 411.6 730.2 411.6 730.2 398.5 730.2 397.5 730.2 395.4 730.2 393.3 730.2 391.2 727.8 391.8 725.2 392.6 722.6 393.5ZM730.3 270.6C727.9 270.6 725.4 270.6 723 270.6 722 270.6 721.1 270.6 720.1 270.6 720 270.6 719.6 271.3 719.6 271.4 716.5 276 713.4 280.6 710.4 285.3 708.9 287.5 707.4 289.7 706 292 705.6 292.5 705.3 293.1 704.9 293.6 704.6 294.1 704.8 294.9 704.8 295.4 704.8 295.6 704.8 298.8 704.8 298.8 705.4 298.8 706 298.8 706.5 298.8 709.5 298.8 712.4 298.8 715.4 298.8 717.8 298.8 720.1 298.8 722.5 298.8 723 298.8 722.7 299.6 722.7 299.9 722.7 301.4 722.7 302.9 722.7 304.4 722.7 305.8 722.7 307.1 722.7 308.5 722.7 309.3 723 309.1 723.8 309.1 725.3 309.1 726.9 309.1 728.4 309.1 728.7 309.1 730.3 309.3 730.3 308.9 730.3 306.2 730.3 303.4 730.3 300.7 730.3 300.4 730.1 298.8 730.5 298.8 731.9 298.8 733.3 298.8 734.6 298.8 734.7 298.8 735.4 298.8 735.4 298.8 735.4 298.2 735.4 297.7 735.4 297.1 735.4 296.9 735.4 293.7 735.4 293.7 734.1 293.7 732.9 293.7 731.6 293.7 731.1 293.7 730.3 294 730.3 293.4 730.3 285.7 730.3 278.1 730.3 270.6ZM722.6 285.9C722.6 287.2 722.6 288.5 722.6 289.7 722.6 290.6 722.6 291.4 722.6 292.3 722.6 292.5 722.7 293.4 722.6 293.6 722.5 293.7 721.6 293.6 721.5 293.6 720.6 293.6 719.7 293.6 718.8 293.6 717.5 293.6 716.2 293.6 715 293.6 716.3 291.6 717.7 289.6 719 287.6 719.6 286.7 720.2 285.9 720.8 285.1 722.4 283.1 722.6 280.7 722.6 278.2 722.6 280.8 722.6 283.4 722.6 285.9ZM763.6 288.5C760.9 285.8 756.2 285.9 752.6 285.9 752 285.9 751.4 285.9 750.8 285.9 750.8 285.9 750.8 284.8 750.8 284.7 750.8 283.4 750.8 282.1 750.8 280.8 750.8 280.7 763.9 280.8 765.2 280.8 765.7 280.8 766.2 281 766.2 280.5 766.2 279.1 766.2 277.7 766.2 276.4 766.2 275.3 766.2 274.2 766.2 273.2 766.2 273.2 764.9 273.2 764.9 273.2 759.2 273.2 753.5 273.2 747.8 273.2 747.2 273.2 746.5 273.2 745.9 273.2 745.7 273.2 745.7 273.6 745.7 273.8 745.4 276 745.1 278.2 744.9 280.4 744.3 284.8 743.8 289.3 743.2 293.7 747 293.7 751.5 293.1 755.1 294.8 757.9 296.2 759 299.4 758.5 302.4 758 305.8 754.4 306.5 751.5 306.5 749.6 306.5 743.2 307 743.2 303.9 742.3 306.5 741.5 309 740.6 311.6 742.3 311.6 744 312.6 745.6 313.2 748 314.1 750.5 314.3 753 314.1 756.9 313.8 761 312.5 763.6 309.4 766.3 306.1 766.2 301.9 766.2 297.8 766.2 295.6 766.2 293.3 765.7 291.1 765.5 290.1 765 288.6 763.7 288.5 763.7 288.5 763.6 288.5 763.6 288.5 761 285.9 766.2 288.5 763.6 288.5Z",
87 "path": "M174.6 216.8C173.4 220.9 172.2 225 171 229.1 168.1 239.1 165.2 249.1 162.3 259.1 158.7 271.6 155 284.2 151.4 296.7 148 308.4 144.6 320.1 141.2 331.8 139 339.3 136.8 346.8 134.7 354.3 134.4 355.4 134.1 356.5 133.7 357.6 133.7 357.7 133.9 358.2 134 358.3 134.3 359 134.5 359.7 134.8 360.5 137.2 367.3 139.7 374.1 142.1 381 146 392 149.9 403 153.9 414.1 158.3 426.5 162.8 439 167.2 451.4 171.1 462.5 175.1 473.6 179 484.7 181.5 491.7 184 498.6 186.4 505.6 186.8 506.7 187.2 507.7 187.5 508.8 187.8 509.6 188.6 510.4 189 511.1 192.8 516.9 196.5 522.6 200.3 528.4 206.5 537.9 212.7 547.4 219 556.9 226.2 567.9 233.4 578.9 240.6 590 247.3 600.3 254.1 610.6 260.8 620.9 265.6 628.2 270.4 635.6 275.2 642.9 276.4 644.8 277.6 646.6 278.9 648.5 279.2 649 279.5 649.5 279.8 649.8 282.7 652.6 285.5 655.4 288.4 658.2 294.6 664.3 300.9 670.5 307.1 676.6 315.5 684.9 323.9 693.2 332.4 701.4 341.8 710.6 351.2 719.9 360.6 729.1 369.8 738.1 378.9 747.1 388.1 756.1 395.8 763.7 403.6 771.3 411.3 778.9 416.4 783.9 421.5 788.9 426.6 793.9 428.2 795.5 429.8 797.3 431.6 798.6 438.9 803.9 446.1 809.2 453.4 814.5 463.7 822 473.9 829.5 484.2 837 487.6 839.5 491.1 842 494.5 844.5 495.3 845.1 496.1 845.7 496.9 846.3 497.2 846.5 497.2 846.6 497.6 846.4 504.7 842.7 511.8 839.1 518.9 835.4 530.3 829.5 541.7 823.6 553.1 817.7 559.2 814.5 565.4 811.4 571.5 808.2 571.9 808 572.3 807.1 572.6 806.8 573.7 805.4 574.8 804 576 802.5 580.2 797.2 584.3 791.9 588.5 786.7 594.7 778.9 600.8 771.1 607 763.3 614.5 753.8 622 744.3 629.5 734.8 637.7 724.5 645.8 714.1 654 703.8 662.1 693.5 670.3 683.2 678.4 672.9 685.9 663.5 693.3 654 700.8 644.6 706.9 636.9 713 629.2 719.1 621.5 723.2 616.4 727.2 611.2 731.3 606.1 732.7 604.4 734 602.6 735.4 600.9 735.2 600.8 734.8 600.8 734.6 600.7 733.8 600.5 733 600.4 732.2 600.2 729.1 599.6 726 598.9 722.9 598.2 718 597.1 713 596 708.1 594.8 701.5 593.2 694.9 591.5 688.3 589.7 680.2 587.5 672.2 585.2 664.1 582.9 654.7 580.1 645.4 577.2 636.1 574.1 625.6 570.6 615.2 567 604.8 563.3 593.4 559.1 582 554.8 570.8 550.2 558.6 545.3 546.6 540.1 534.6 534.8 521.9 529.1 509.3 523.1 496.8 516.8 483.7 510.2 470.7 503.4 457.9 496.2 444.6 488.7 431.4 480.9 418.5 472.8 405.1 464.4 392 455.6 379.1 446.4 365.9 437 352.9 427.1 340.3 416.9 327.4 406.4 314.8 395.5 302.7 384.2 290.3 372.6 278.3 360.6 266.8 348.1 255.1 335.3 243.8 322.1 233.2 308.4 222.3 294.4 212 279.9 202.4 265 192.5 249.7 183.4 233.9 175 217.8 175 217.4 174.8 217.1 174.6 216.8ZM172.1 214.2C170.7 218.7 169.3 223.3 167.8 227.8 164.5 238.5 161.1 249.2 157.8 259.9 153.9 272.4 150 285 146.1 297.5 143 307.5 139.9 317.4 136.7 327.4 135.9 330.1 135 332.7 134.2 335.4 134 336.1 133.6 336.7 133.8 337.4 135.4 342.2 137 347.1 138.6 351.9 141.9 361.9 145.2 371.8 148.6 381.8 152.7 394.1 156.8 406.5 160.9 418.8 164.9 430.8 168.9 442.8 172.9 454.8 175.9 463.7 178.8 472.6 181.8 481.4 182.6 483.8 183.4 486.2 184.2 488.7 184.4 489.4 184.6 490.1 184.9 490.8 187.2 495 189.5 499.2 191.8 503.4 196.8 512.6 201.9 521.8 206.9 531 213.2 542.4 219.4 553.9 225.7 565.3 231.7 576.2 237.6 587.1 243.6 598 247.8 605.6 251.9 613.2 256.1 620.8 257.3 623 258.2 625.4 259.9 627.2 264.1 631.7 268.3 636.2 272.5 640.7 280.2 648.9 287.9 657.2 295.5 665.4 304.5 675 313.5 684.7 322.4 694.3 330.5 703 338.6 711.7 346.7 720.4 351.8 725.8 356.8 731.3 361.9 736.7 363.5 738.4 365 740 366.6 741.6 372.3 747.3 378 753 383.7 758.7 392.5 767.5 401.2 776.2 410 785 419.1 794.1 428.3 803.3 437.4 812.4 444.2 819.2 451.1 826.1 457.9 832.9 459.6 834.6 461.3 836.3 463 838 463.3 838.3 463.6 838.6 463.8 838.8 463.9 838.9 465.1 838.7 465.3 838.6 475.9 837.2 486.5 835.8 497 834.5 505.6 833.4 514.1 832.3 522.7 831.2 523 831.2 523.7 830.1 523.9 829.9 525.1 828.6 526.3 827.2 527.6 825.9 532.1 820.9 536.7 815.9 541.2 810.9 547.9 803.5 554.6 796.1 561.4 788.7 569.6 779.7 577.7 770.7 585.9 761.8 594.8 752 603.6 742.3 612.5 732.5 621.3 722.8 630.1 713.1 639 703.4 647 694.5 655.1 685.7 663.1 676.8 669.6 669.6 676.2 662.4 682.7 655.2 687 650.5 691.3 645.8 695.6 641 696.6 639.9 697.7 638.7 698.7 637.6 698.9 637.4 699.6 636.9 699.6 636.6 699.6 636.5 696.6 635.7 696.5 635.7 693.5 634.8 690.4 633.9 687.4 633 682.6 631.5 677.8 630 673 628.4 666.6 626.3 660.1 624.1 653.8 621.8 645.9 619 638.1 616.1 630.3 613.1 621.2 609.6 612.1 606 603.1 602.2 592.9 598 582.8 593.6 572.8 589 561.8 584 550.8 578.8 540 573.4 528.3 567.6 516.7 561.6 505.2 555.3 493 548.7 480.9 541.8 469 534.6 456.5 527.1 444.1 519.3 431.9 511.2 419.2 502.8 406.7 494 394.5 484.9 381.8 475.5 369.5 465.8 357.4 455.7 345 445.3 332.8 434.6 321.1 423.4 309.1 412 297.4 400.2 286.2 388 274.7 375.5 263.7 362.6 253.2 349.3 242.5 335.7 232.3 321.7 222.8 307.2 213 292.4 203.9 277.2 195.5 261.7 186.8 246.5 179 230.5 172.1 214.2ZM169.5 204C168.8 207.8 168.1 211.6 167.3 215.4 165.5 224.9 163.7 234.5 161.9 244 159.5 256.5 157.1 269 154.7 281.5 152.3 294.2 149.8 307 147.4 319.7 145.5 329.9 143.5 340.1 141.6 350.3 140.7 355.2 139.7 360.1 138.8 365 138.7 365.7 139.1 366.4 139.3 367 140.2 369.6 141.1 372.2 142 374.8 145.4 384.5 148.7 394.3 152.1 404 156.4 416.4 160.7 428.7 165 441.1 168.8 452.1 172.6 463 176.4 474 178.3 479.5 180.2 485 182.1 490.5 182.3 491.2 182.7 491.8 183 492.4 184.2 494.8 185.4 497.1 186.5 499.5 190.9 508.4 195.4 517.2 199.8 526.1 205.6 537.7 211.4 549.3 217.2 560.9 222.7 571.9 228.2 583 233.8 594 237.4 601.2 241 608.3 244.6 615.5 245.2 616.6 245.7 617.7 246.3 618.8 246.7 619.6 247.6 620.4 248.2 621.1 252.8 626.6 257.4 632.1 262 637.7 269.5 646.7 276.9 655.6 284.4 664.6 292.8 674.7 301.3 684.9 309.7 695 317.2 704 324.8 713.1 332.3 722.1 337 727.8 341.8 733.5 346.5 739.1 347.2 740 347.9 740.8 348.7 741.7 348.9 741.9 349.2 742 349.4 742.2 350.2 742.7 350.9 743.2 351.7 743.7 358.7 748.5 365.8 753.3 372.8 758.1 383.3 765.3 393.9 772.5 404.4 779.7 414.6 786.6 424.7 793.6 434.9 800.5 440.8 804.5 446.7 808.6 452.7 812.6 456.3 815.1 459.5 818.1 462.9 820.8 472.5 828.7 482.1 836.7 491.7 844.6 498.5 850.2 505.4 855.9 512.2 861.5 512.8 862 512.7 861.9 513.3 861.3 514.2 860.3 515.2 859.2 516.1 858.2 520 853.9 524 849.6 527.9 845.3 534 838.6 540.2 831.9 546.3 825.2 554 816.8 561.7 808.3 569.4 799.9 578.1 790.4 586.7 781 595.4 771.5 604.4 761.7 613.3 751.9 622.3 742.1 630.9 732.6 639.6 723.2 648.2 713.7 655.9 705.3 663.6 696.9 671.3 688.5 677.4 681.8 683.5 675.1 689.6 668.4 693.5 664.1 697.4 659.9 701.3 655.6 702.4 654.4 703.5 653.2 704.6 652 704.6 652 704.6 652 704.6 652 704.6 652 704.6 652 704.6 652 704.6 652.1 701.6 651.3 701.5 651.3 698.5 650.5 695.5 649.5 692.6 648.6 687.9 647.1 683.1 645.5 678.4 643.8 672.1 641.6 665.8 639.2 659.5 636.9 651.8 634 644.1 630.9 636.4 627.8 627.5 624.1 618.6 620.3 609.7 616.4 599.7 612 589.8 607.4 580 602.7 569.2 597.5 558.4 592.1 547.7 586.6 536.2 580.6 524.8 574.4 513.4 568 501.4 561.2 489.5 554.2 477.7 546.9 465.3 539.3 453.1 531.4 441.1 523.3 428.6 514.8 416.3 506.1 404.2 497 391.7 487.7 379.5 478 367.5 468 355.2 457.8 343.2 447.2 331.5 436.3 319.6 425.2 308 413.6 296.8 401.7 285.4 389.6 274.5 377.1 264 364.3 253.3 351.2 243.2 337.8 233.6 323.9 223.8 309.8 214.6 295.4 206.1 280.5 197.4 265.4 189.4 249.9 182.1 234 177.7 224.2 173.5 214.2 169.5 204ZM866 183.5C863.9 179.4 861.1 176.2 857.1 174 851.9 171.1 846.2 168.9 840.7 166.5 829.5 161.7 818.2 157.4 806.7 153.4 783.6 145.4 760 138.9 736.3 132.9 711.7 126.7 687.1 120.9 662.3 115.7 637.1 110.4 611.7 105.6 586.3 101.4 561.2 97.2 536 93.1 510.5 91.1 497.8 90.1 485 89.9 472.4 91.3 465.9 92 459.4 93.2 453 94.2 446.6 95.2 440.1 96.2 433.7 97.3 408.2 101.5 382.8 106 357.4 111 332.2 115.9 307.1 121.2 282.1 126.9 257.2 132.5 232.6 139.2 208.4 147.3 196.3 151.4 184.2 155.8 172.3 160.5 166.4 162.8 160.5 165.2 154.6 167.7 151.7 168.9 148.8 170.2 145.8 171.4 143.2 172.5 140.6 173.5 138.1 174.7 134 176.7 130.6 179.7 128.3 183.6 127 185.8 126.2 188.2 125.3 190.6 124.2 193.6 123.1 196.6 122.1 199.6 118.1 211.5 114.9 223.7 112.5 236 107.7 260.4 106 285.4 106.8 310.2 107.2 322.7 108.2 335.3 109.7 347.7 111.2 360.2 112.7 372.8 115.1 385.2 119.8 410.4 126.7 435.1 134.8 459.3 138.9 471.4 143.3 483.5 147.9 495.4 152.2 506.5 157.5 517.3 162.7 528 173 549.2 184.4 569.8 196.6 589.9 208.8 609.9 221.9 629.3 235.7 648.1 249.5 666.8 264.1 685 279.3 702.6 295.3 721.1 311.7 739.2 328.6 756.9 345.6 774.8 363 792.2 381 809 398.9 825.9 417.4 842.2 436.4 857.8 445.6 865.4 454.9 872.8 464.2 880.2 473.6 887.7 483.1 895.1 492 903.2 494.3 905.2 496.5 907.3 498.7 909.5 498.9 909.7 499.7 910.8 500 910.8 500.2 910.8 500.5 910.8 500.7 910.8 501.2 910.8 502 911 502.5 910.8 507.3 907.1 512 903.3 516.8 899.6 526.2 892.1 535.6 884.6 544.9 876.9 563.3 861.7 581.4 846.2 599.2 830.3 616.9 814.5 634.1 798.2 651 781.5 667.9 764.7 684.4 747.5 700.3 729.7 716.3 711.8 731.8 693.4 746.5 674.4 761 655.7 774.8 636.5 787.8 616.8 800.7 597.2 812.8 577 823.8 556.2 835 535.1 845.2 513.5 854.3 491.4 863.4 469.1 871.2 446.3 877.3 423 883.4 399.9 887.8 376.4 890.3 352.7 892.9 328.6 893.4 304.3 892 280 891.8 276.9 891 273.8 890.3 270.7 889.7 267.7 889 264.6 888.4 261.6 887.2 255.7 886 249.9 884.7 244 882.3 233 879.7 222 876.5 211.1 873.4 201.8 870.1 192.5 866 183.5 863.5 178.4 878.8 211.7 866 183.5ZM814.8 393.5C808.1 418.2 799.5 442.5 789.4 466 780 487.9 770 509.6 758.5 530.5 747.4 550.7 735.1 570.3 722 589.3 708.8 608.4 694.7 626.8 680 644.8 664.8 663.4 649 681.5 632.7 699.1 615.9 717.3 598.5 734.9 580.5 752 562.5 769.1 544.1 785.7 525.1 801.6 515.7 809.5 506.1 817.3 496.5 824.9 496.1 825.2 495.2 826.3 494.7 826.3 494 826.3 493.3 826.3 492.6 826.3 492 826.3 491.4 825.5 491 825.1 490.5 824.6 490 824.1 489.5 823.6 488.4 822.6 487.2 821.5 486.1 820.5 481.6 816.6 476.9 813.1 472.2 809.4 469.9 807.6 467.6 805.7 465.3 803.8 463.1 801.9 461 799.8 458.8 797.8 454.2 793.7 449.7 789.6 445.2 785.5 435.9 777 426.6 768.5 417.5 759.8 408.4 751.1 399.5 742.3 390.9 733.2 386.7 728.8 382.7 724.3 378.4 720 374.2 715.8 370 711.5 365.8 707.2 349.1 690 332.9 672.5 317.4 654.3 301.8 636 286.9 617 273.1 597.3 259.2 577.5 246.4 556.9 234.5 535.8 222.8 515 212.1 493.7 202.6 471.8 193.1 449.9 184.8 427.4 177.9 404.6 176.1 398.6 174.4 392.6 173.1 386.5 171.7 380.1 170.6 373.6 169.6 367.1 167.6 354.2 166.3 341.2 165.5 328.2 164.7 315.3 164.3 302.3 164.5 289.3 164.7 276.7 165.9 264.2 167.5 251.7 167.9 248.5 168.3 245.4 168.7 242.2 168.9 240.6 169.1 239.1 169.3 237.5 169.5 235.9 169.6 234.3 169.8 232.7 170.1 230.3 171.1 228.1 171.7 225.7 172 224.5 172.2 223.2 172.2 221.9 172.2 220.8 172.8 220.1 173.6 219.5 174.6 218.8 175.6 218.3 176.5 217.5 177.1 217 177.6 216.6 178.4 216.3 179.2 216 180.1 215.7 180.9 215.3 183.9 214.2 186.8 213 189.8 211.9 195.7 209.7 201.6 207.5 207.6 205.3 231.3 196.7 255.3 189 279.7 182.4 292 179.1 304.3 176.1 316.7 173.5 322.9 172.2 329.1 170.6 335.4 169.3 341.7 167.9 348 166.6 354.3 165.4 379.8 160.4 405.4 156.3 431.1 152.5 444 150.6 457 148.8 470 147 473.2 146.6 476.5 146.1 479.7 145.7 481.3 145.5 482.8 145.3 484.4 145.1 485.7 144.9 487.1 145 488.4 145.1 493.9 145.1 499.5 145.3 504.9 146.3 506.2 146.5 507.4 146.8 508.6 147.1 510.1 147.5 511.5 147.8 513 148 516.1 148.4 519.2 148.9 522.3 149.3 528.6 150.2 534.8 151.1 541.1 152 553.7 153.8 566.4 155.7 579 157.7 604.4 161.7 629.7 166 654.8 171.4 680 176.8 705 183.2 729.7 190.3 742.1 193.9 754.4 197.7 766.6 201.7 772.7 203.7 778.7 205.8 784.7 207.9 787.7 209 790.7 210 793.7 211.1 795.1 211.6 796.6 212.1 798 212.7 798.7 213 799.4 213.2 800.1 213.5 800.8 213.8 801.9 214 802.4 214.5 803.6 215.7 805.3 216.5 806.3 217.9 806.8 218.7 807.1 219.5 807.2 220.5 807.3 221.2 807.2 221.8 807.4 222.5 807.7 223.4 807.9 224.3 808.1 225.2 809.8 231.5 811.2 237.9 812.3 244.4 813.4 250.8 814.1 257.2 814.5 263.6 814.7 266.8 814.8 270 814.9 273.2 814.9 274 814.9 274.7 814.9 275.5 814.9 276.3 815.2 277.1 815.3 277.8 815.7 279.5 816 281.1 816.4 282.8 821.3 306.5 822.7 330.7 820.7 354.8 819.6 367.7 817.6 380.7 814.8 393.5 807.1 421.7 822.5 357.6 814.8 393.5ZM617.6 393.5C616.1 389 614.6 384.5 613.1 379.9 612.9 379.3 612.7 378.7 612.5 378.1 612.4 377.7 612.5 377.1 612.4 376.7 612.3 376.1 612.2 375.5 612.1 374.9 611.8 373.8 611.4 372.8 610.8 371.9 609.7 370.1 608.1 368.5 606.5 367 604.7 365.2 602.4 362.7 599.6 362.7 601.6 360.7 604.3 360 606.5 358.3 607.6 357.4 608.5 356.5 609.7 355.7 610.5 355.2 611.6 354.7 612.1 353.8 612.3 353.4 612.4 352.9 612.4 352.5 612.9 352 613.3 351.5 613.7 350.9 614.4 349.8 614.7 348.6 614.9 347.3 615.1 345.1 615 342.9 615 340.7 615 338.4 615 336.1 615 333.8 615 331.4 615 329 614.4 326.6 613.1 321.5 610 316.8 606.4 313.1 604.7 311.4 603 309.9 601 308.6 598.3 306.9 595.5 305.5 592.7 304.1 589.9 302.7 586.9 301.8 583.8 301.4 581.4 301.1 579 301.1 576.6 301.1 573.9 301.1 571.2 301.1 568.5 301.1 556.2 301.1 543.8 301.1 531.5 301.1 526.9 301.1 522.3 301.1 517.7 301.1 516.9 301.1 516.1 301.1 515.2 301.1 515.1 301.1 515.2 305.3 515.2 305.6 515.2 308.8 515.2 311.9 515.2 315.1 515.2 316.2 515.2 317.3 515.2 318.4 515.2 318.9 515 319.1 515.5 319.1 516.7 319.1 528 319 528 319.2 528 327.2 528 335.2 528 343.2 528 355.8 528 368.3 528 380.9 528 384.6 528 388.3 528 392 528 392.2 528.1 393.4 527.9 393.4 525.4 393.4 522.8 393.4 520.3 393.4 518.9 393.4 517.6 393.4 516.2 393.4 515.9 393.4 515.2 393.2 515.2 393.6 515.2 395.7 515.2 397.8 515.2 400 515.2 401 515.2 414 515.2 414 524.7 414 534.3 414 543.8 414 549.3 414 554.8 414 560.2 414 561.4 414 562.5 414 563.7 414 564 414 563.8 411.1 563.8 410.7 563.8 405.1 563.8 399.6 563.8 394 563.8 393.4 563.9 393.5 563.3 393.5 562 393.5 560.7 393.5 559.3 393.5 557.8 393.5 556.3 393.5 554.8 393.5 554.6 393.5 553.5 393.7 553.5 393.4 553.5 388.4 553.5 383.4 553.5 378.4 553.5 375.6 553.5 372.9 553.5 370.1 553.5 369.4 553.5 368.8 553.5 368.1 553.5 367.7 554.2 367.9 554.5 367.9 557.4 367.9 560.2 367.9 563.1 367.9 565 367.9 566.9 367.9 568.8 367.9 570.1 367.9 571.6 367.7 572.8 368.1 573.9 368.4 574.8 369 575.7 369.7 576.8 370.6 578.3 371.8 578.9 373.1 579.2 373.8 579.2 374.5 579.2 375.3 579.2 376.6 579.6 377.7 580.2 378.9 580.7 380 581.3 381 581.6 382.2 581.7 382.6 581.7 383 581.8 383.4 581.9 384 582 384.6 582.1 385.1 583.1 390.9 584.2 396.6 585.2 402.4 585.6 404.9 586.1 407.3 586.5 409.8 586.6 410.3 586.7 410.8 586.8 411.3 586.8 411.4 587.2 411.4 587.4 411.4 597.8 411.4 608.3 411.4 618.7 411.4 619.2 411.4 619.6 411.4 620.1 411.4 620.2 411.4 620.2 410.7 620.2 410.6 620.2 408.2 620.2 405.7 620.2 403.3 620.2 398.3 620.2 393.3 620.2 388.4 620.2 388.4 620.2 388.4 620.2 388.4 619.3 390.1 618.5 391.8 617.6 393.5ZM592 339.7C592 342 589.2 342.8 587.7 344.1 587.4 344.3 587.1 344.6 586.9 344.8 586.7 344.8 586.4 344.8 586.2 344.9 585.8 345 585.4 345.2 585.1 345.4 584.4 345.9 583.9 346.6 583.2 347 582.1 347.5 580.7 347.3 579.6 347.3 577.9 347.3 576.3 347.3 574.6 347.3 573.9 347.3 573.2 347.3 572.5 347.3 569.5 347.3 566.4 347.3 563.4 347.3 563 347.3 558.8 347.4 558.8 347.2 558.8 337.9 558.8 328.5 558.8 319.2 558.8 319.1 571.7 319.2 573 319.2 577 319.2 581 319.1 584.9 320.1 586.4 320.5 587.8 321 589.2 321.6 590.1 322.1 591 323.2 591.6 324 593.1 325.7 594.1 327.8 594.5 330 594.6 330.7 594.6 331.3 594.6 332 594.3 332.6 594 333.2 593.7 333.9 593.3 334.7 592.9 335.5 592.6 336.3 592.1 337.4 592 338.5 592 339.7ZM722.6 393.5C722.6 384.2 722.6 374.9 722.6 365.6 722.6 357.1 720.9 348 714.6 341.9 707.5 335.1 696.4 333.9 687 334.7 685.1 334.9 683.2 335.3 681.4 336.1 680.4 336.5 679.5 336.9 678.6 337.6 678 338.1 677.3 338.5 676.7 338.8 673.6 340.4 670.5 341.6 668.8 344.9 668.8 335.9 668.8 326.8 668.8 317.8 668.8 311.9 668.8 306 668.8 300.1 668.8 298.4 668.8 296.6 668.8 294.9 668.8 294.4 669.1 293.7 668.5 293.7 657.9 293.7 647.3 293.7 636.7 293.7 635.5 293.7 634.2 293.7 633 293.7 633 293.7 633 297.8 633 298.1 633 303.4 633 308.7 633 314 633 314.3 633.8 314.2 634 314.2 635.4 314.2 636.7 314.2 638.1 314.2 640.6 314.2 643.2 314.2 645.7 314.2 645.9 314.2 645.8 319.4 645.8 319.8 645.8 331.2 645.8 342.6 645.8 353.9 645.8 364.9 645.8 375.8 645.8 386.8 645.8 388 645.8 389.2 645.8 390.3 645.8 391.2 645.7 391 644.6 391 641.6 391 638.7 391 635.7 391 634.8 391 633.9 391 633 391 632.9 391 632.9 391.9 632.9 392 632.9 397.7 632.9 403.4 632.9 409 632.9 409.8 632.9 410.5 632.9 411.3 632.9 411.5 633 411.5 633.2 411.5 634.5 411.5 635.9 411.5 637.2 411.5 649.1 411.5 661 411.5 672.9 411.5 673.4 411.5 681.5 411.5 681.5 411.5 681.5 406.5 681.5 401.5 681.5 396.5 681.5 394.7 681.5 392.9 681.5 391.1 681.5 391.1 675.6 391.1 675.2 391.1 674.8 391.1 668.7 391.1 668.7 391.1 668.7 389.8 668.7 388.5 668.7 387.3 668.7 381.2 668.7 375 668.7 368.9 668.7 366.5 668.7 364.2 668.7 361.8 668.7 361.3 668.7 360.9 668.7 360.4 668.7 360 670.3 358.8 670.6 358.5 671.7 357.5 672.8 356.5 674.2 355.8 674.7 355.5 675.3 355.3 675.8 355.3 676.5 355.2 676.8 354.8 677.4 354.3 678.5 353.5 679.7 353 681 352.8 683.6 352.4 685.8 352.7 687.9 354.2 689.1 355.1 690.1 356.1 691.2 357.2 692 358 692.7 358.8 693.3 359.8 694.2 361.6 694.3 363.7 694.3 365.7 694.4 369.3 694.3 372.9 694.3 376.6 694.3 387.8 694.3 399 694.3 410.3 694.3 410.9 694 411.6 694.7 411.6 696.4 411.6 698.1 411.6 699.8 411.6 706 411.6 712.3 411.6 718.5 411.6 722.4 411.6 726.3 411.6 730.2 411.6 730.2 411.6 730.2 398.5 730.2 397.5 730.2 395.4 730.2 393.3 730.2 391.2 727.8 391.8 725.2 392.6 722.6 393.5ZM730.3 270.6C727.9 270.6 725.4 270.6 723 270.6 722 270.6 721.1 270.6 720.1 270.6 720 270.6 719.6 271.3 719.6 271.4 716.5 276 713.4 280.6 710.4 285.3 708.9 287.5 707.4 289.7 706 292 705.6 292.5 705.3 293.1 704.9 293.6 704.6 294.1 704.8 294.9 704.8 295.4 704.8 295.6 704.8 298.8 704.8 298.8 705.4 298.8 706 298.8 706.5 298.8 709.5 298.8 712.4 298.8 715.4 298.8 717.8 298.8 720.1 298.8 722.5 298.8 723 298.8 722.7 299.6 722.7 299.9 722.7 301.4 722.7 302.9 722.7 304.4 722.7 305.8 722.7 307.1 722.7 308.5 722.7 309.3 723 309.1 723.8 309.1 725.3 309.1 726.9 309.1 728.4 309.1 728.7 309.1 730.3 309.3 730.3 308.9 730.3 306.2 730.3 303.4 730.3 300.7 730.3 300.4 730.1 298.8 730.5 298.8 731.9 298.8 733.3 298.8 734.6 298.8 734.7 298.8 735.4 298.8 735.4 298.8 735.4 298.2 735.4 297.7 735.4 297.1 735.4 296.9 735.4 293.7 735.4 293.7 734.1 293.7 732.9 293.7 731.6 293.7 731.1 293.7 730.3 294 730.3 293.4 730.3 285.7 730.3 278.1 730.3 270.6ZM722.6 285.9C722.6 287.2 722.6 288.5 722.6 289.7 722.6 290.6 722.6 291.4 722.6 292.3 722.6 292.5 722.7 293.4 722.6 293.6 722.5 293.7 721.6 293.6 721.5 293.6 720.6 293.6 719.7 293.6 718.8 293.6 717.5 293.6 716.2 293.6 715 293.6 716.3 291.6 717.7 289.6 719 287.6 719.6 286.7 720.2 285.9 720.8 285.1 722.4 283.1 722.6 280.7 722.6 278.2 722.6 280.8 722.6 283.4 722.6 285.9ZM763.6 288.5C760.9 285.8 756.2 285.9 752.6 285.9 752 285.9 751.4 285.9 750.8 285.9 750.8 285.9 750.8 284.8 750.8 284.7 750.8 283.4 750.8 282.1 750.8 280.8 750.8 280.7 763.9 280.8 765.2 280.8 765.7 280.8 766.2 281 766.2 280.5 766.2 279.1 766.2 277.7 766.2 276.4 766.2 275.3 766.2 274.2 766.2 273.2 766.2 273.2 764.9 273.2 764.9 273.2 759.2 273.2 753.5 273.2 747.8 273.2 747.2 273.2 746.5 273.2 745.9 273.2 745.7 273.2 745.7 273.6 745.7 273.8 745.4 276 745.1 278.2 744.9 280.4 744.3 284.8 743.8 289.3 743.2 293.7 747 293.7 751.5 293.1 755.1 294.8 757.9 296.2 759 299.4 758.5 302.4 758 305.8 754.4 306.5 751.5 306.5 749.6 306.5 743.2 307 743.2 303.9 742.3 306.5 741.5 309 740.6 311.6 742.3 311.6 744 312.6 745.6 313.2 748 314.1 750.5 314.3 753 314.1 756.9 313.8 761 312.5 763.6 309.4 766.3 306.1 766.2 301.9 766.2 297.8 766.2 295.6 766.2 293.3 765.7 291.1 765.5 290.1 765 288.6 763.7 288.5 763.7 288.5 763.6 288.5 763.6 288.5 761 285.9 766.2 288.5 763.6 288.5Z",
88 "width": 1000
88 "width": 1000
89 },
89 },
90 "search": [
90 "search": [
91 "rhodecode"
91 "rhodecode"
92 ]
92 ]
93 },
93 },
94 {
94 {
95 "uid": "e5ad8728e6d6290aff4b6ffcfcaa9167",
95 "uid": "e5ad8728e6d6290aff4b6ffcfcaa9167",
96 "css": "up",
96 "css": "up",
97 "code": 59442,
97 "code": 59442,
98 "src": "custom_icons",
98 "src": "custom_icons",
99 "selected": true,
99 "selected": true,
100 "svg": {
100 "svg": {
101 "path": "M686.5 595.8L513.6 379.1C506.3 369.9 492.4 369.9 485.1 379.1L312.2 595.8C302.7 607.8 311.2 625.4 326.5 625.4H672.2C687.5 625.4 696 607.8 686.5 595.8Z",
101 "path": "M686.5 595.8L513.6 379.1C506.3 369.9 492.4 369.9 485.1 379.1L312.2 595.8C302.7 607.8 311.2 625.4 326.5 625.4H672.2C687.5 625.4 696 607.8 686.5 595.8Z",
102 "width": 1000
102 "width": 1000
103 },
103 },
104 "search": [
104 "search": [
105 "up"
105 "up"
106 ]
106 ]
107 },
107 },
108 {
108 {
109 "uid": "6e459e39444c93a2c017f258186765d6",
109 "uid": "6e459e39444c93a2c017f258186765d6",
110 "css": "unlock",
110 "css": "unlock",
111 "code": 59399,
111 "code": 59399,
112 "src": "custom_icons",
112 "src": "custom_icons",
113 "selected": true,
113 "selected": true,
114 "svg": {
114 "svg": {
115 "path": "M780.8 434.6H396.2V342.3C396.2 284.6 438.5 238.5 492.3 226.9 492.3 226.9 492.3 226.9 496.2 226.9 503.8 226.9 507.7 226.9 515.4 226.9 515.4 226.9 519.2 226.9 519.2 226.9 519.2 226.9 519.2 226.9 523.1 226.9 530.8 226.9 538.5 226.9 546.2 230.8 546.2 230.8 546.2 230.8 546.2 230.8 553.8 230.8 557.7 234.6 565.4 238.5 565.4 238.5 569.2 238.5 569.2 242.3 573.1 246.2 580.8 246.2 584.6 250 584.6 250 584.6 250 584.6 250 588.5 253.8 596.2 257.7 600 261.5 600 261.5 603.8 265.4 603.8 265.4 607.7 269.2 611.5 273.1 615.4 276.9 615.4 276.9 615.4 276.9 619.2 280.8 623.1 284.6 626.9 292.3 630.8 300 630.8 300 630.8 303.8 630.8 303.8 634.6 307.7 634.6 315.4 634.6 319.2 634.6 319.2 634.6 323.1 634.6 323.1 634.6 323.1 634.6 323.1 634.6 326.9 638.5 338.5 646.2 346.2 657.7 346.2H715.4C730.8 346.2 742.3 334.6 738.5 319.2 738.5 319.2 738.5 319.2 738.5 319.2 738.5 319.2 738.5 315.4 738.5 315.4 738.5 307.7 734.6 303.8 734.6 296.2 734.6 292.3 734.6 292.3 730.8 288.5 730.8 273.1 730.8 269.2 726.9 261.5 726.9 261.5 726.9 257.7 723.1 257.7 719.2 250 715.4 242.3 711.5 234.6 711.5 234.6 707.7 230.8 707.7 230.8 703.8 223.1 700 219.2 696.2 215.4 696.2 211.5 692.3 211.5 692.3 207.7 688.5 203.8 684.6 196.2 680.8 192.3 680.8 192.3 676.9 188.5 676.9 188.5 669.2 180.8 665.4 176.9 657.7 169.2 657.7 169.2 653.8 169.2 653.8 165.4 650 161.5 642.3 157.7 634.6 153.8 630.8 153.8 630.8 150 626.9 150 623.1 146.2 615.4 142.3 611.5 142.3 607.7 142.3 607.7 138.5 603.8 138.5 596.2 134.6 588.5 130.8 580.8 130.8 580.8 130.8 580.8 130.8 580.8 130.8 573.1 126.9 565.4 126.9 553.8 123.1 550 123.1 550 123.1 546.2 123.1 538.5 123.1 534.6 123.1 526.9 119.2 523.1 119.2 519.2 119.2 519.2 119.2 511.5 119.2 503.8 119.2 496.2 119.2 496.2 119.2 492.3 119.2 492.3 119.2 484.6 119.2 476.9 123.1 465.4 123.1 461.5 123.1 453.8 126.9 450 126.9 450 126.9 446.2 126.9 446.2 126.9 353.8 153.8 288.5 242.3 288.5 342.3V434.6H246.2C230.8 434.6 223.1 446.2 223.1 457.7V857.7C223.1 873.1 234.6 880.8 246.2 880.8H780.8C796.2 880.8 803.8 869.2 803.8 857.7V457.7C807.7 446.2 796.2 434.6 780.8 434.6Z",
115 "path": "M780.8 434.6H396.2V342.3C396.2 284.6 438.5 238.5 492.3 226.9 492.3 226.9 492.3 226.9 496.2 226.9 503.8 226.9 507.7 226.9 515.4 226.9 515.4 226.9 519.2 226.9 519.2 226.9 519.2 226.9 519.2 226.9 523.1 226.9 530.8 226.9 538.5 226.9 546.2 230.8 546.2 230.8 546.2 230.8 546.2 230.8 553.8 230.8 557.7 234.6 565.4 238.5 565.4 238.5 569.2 238.5 569.2 242.3 573.1 246.2 580.8 246.2 584.6 250 584.6 250 584.6 250 584.6 250 588.5 253.8 596.2 257.7 600 261.5 600 261.5 603.8 265.4 603.8 265.4 607.7 269.2 611.5 273.1 615.4 276.9 615.4 276.9 615.4 276.9 619.2 280.8 623.1 284.6 626.9 292.3 630.8 300 630.8 300 630.8 303.8 630.8 303.8 634.6 307.7 634.6 315.4 634.6 319.2 634.6 319.2 634.6 323.1 634.6 323.1 634.6 323.1 634.6 323.1 634.6 326.9 638.5 338.5 646.2 346.2 657.7 346.2H715.4C730.8 346.2 742.3 334.6 738.5 319.2 738.5 319.2 738.5 319.2 738.5 319.2 738.5 319.2 738.5 315.4 738.5 315.4 738.5 307.7 734.6 303.8 734.6 296.2 734.6 292.3 734.6 292.3 730.8 288.5 730.8 273.1 730.8 269.2 726.9 261.5 726.9 261.5 726.9 257.7 723.1 257.7 719.2 250 715.4 242.3 711.5 234.6 711.5 234.6 707.7 230.8 707.7 230.8 703.8 223.1 700 219.2 696.2 215.4 696.2 211.5 692.3 211.5 692.3 207.7 688.5 203.8 684.6 196.2 680.8 192.3 680.8 192.3 676.9 188.5 676.9 188.5 669.2 180.8 665.4 176.9 657.7 169.2 657.7 169.2 653.8 169.2 653.8 165.4 650 161.5 642.3 157.7 634.6 153.8 630.8 153.8 630.8 150 626.9 150 623.1 146.2 615.4 142.3 611.5 142.3 607.7 142.3 607.7 138.5 603.8 138.5 596.2 134.6 588.5 130.8 580.8 130.8 580.8 130.8 580.8 130.8 580.8 130.8 573.1 126.9 565.4 126.9 553.8 123.1 550 123.1 550 123.1 546.2 123.1 538.5 123.1 534.6 123.1 526.9 119.2 523.1 119.2 519.2 119.2 519.2 119.2 511.5 119.2 503.8 119.2 496.2 119.2 496.2 119.2 492.3 119.2 492.3 119.2 484.6 119.2 476.9 123.1 465.4 123.1 461.5 123.1 453.8 126.9 450 126.9 450 126.9 446.2 126.9 446.2 126.9 353.8 153.8 288.5 242.3 288.5 342.3V434.6H246.2C230.8 434.6 223.1 446.2 223.1 457.7V857.7C223.1 873.1 234.6 880.8 246.2 880.8H780.8C796.2 880.8 803.8 869.2 803.8 857.7V457.7C807.7 446.2 796.2 434.6 780.8 434.6Z",
116 "width": 1000
116 "width": 1000
117 },
117 },
118 "search": [
118 "search": [
119 "unlock"
119 "unlock"
120 ]
120 ]
121 },
121 },
122 {
122 {
123 "uid": "b077586592b9b69166b981325446c836",
123 "uid": "b077586592b9b69166b981325446c836",
124 "css": "delete",
124 "css": "delete",
125 "code": 59392,
125 "code": 59392,
126 "src": "custom_icons",
126 "src": "custom_icons",
127 "selected": true,
127 "selected": true,
128 "svg": {
128 "svg": {
129 "path": "M515.4 92.3C303.8 92.3 130.8 265.4 130.8 476.9 130.8 688.5 303.8 861.5 515.4 861.5S900 688.5 900 476.9C900 265.4 726.9 92.3 515.4 92.3ZM742.3 507.7C742.3 523.1 730.8 534.6 711.5 534.6H315.4C300 534.6 284.6 523.1 284.6 507.7V446.2C284.6 430.8 296.2 419.2 315.4 419.2H711.5C726.9 419.2 742.3 430.8 742.3 446.2V507.7Z",
129 "path": "M515.4 92.3C303.8 92.3 130.8 265.4 130.8 476.9 130.8 688.5 303.8 861.5 515.4 861.5S900 688.5 900 476.9C900 265.4 726.9 92.3 515.4 92.3ZM742.3 507.7C742.3 523.1 730.8 534.6 711.5 534.6H315.4C300 534.6 284.6 523.1 284.6 507.7V446.2C284.6 430.8 296.2 419.2 315.4 419.2H711.5C726.9 419.2 742.3 430.8 742.3 446.2V507.7Z",
130 "width": 1000
130 "width": 1000
131 },
131 },
132 "search": [
132 "search": [
133 "delete"
133 "delete"
134 ]
134 ]
135 },
135 },
136 {
136 {
137 "uid": "dca63ad885c0d6f1780a8d1d55bc2380",
137 "uid": "dca63ad885c0d6f1780a8d1d55bc2380",
138 "css": "ok",
138 "css": "ok",
139 "code": 59393,
139 "code": 59393,
140 "src": "custom_icons",
140 "src": "custom_icons",
141 "selected": true,
141 "selected": true,
142 "svg": {
142 "svg": {
143 "path": "M515.4 115.4C303.8 115.4 130.8 288.5 130.8 500 130.8 711.5 303.8 884.6 515.4 884.6S900 711.5 900 500C900 288.5 726.9 115.4 515.4 115.4ZM753.8 411.5L450 715.4C438.5 726.9 423.1 726.9 411.5 715.4L273.1 576.9C261.5 565.4 261.5 550 273.1 538.5L315.4 496.2C326.9 484.6 342.3 484.6 353.8 496.2L411.5 553.8C423.1 565.4 438.5 565.4 450 553.8L669.2 334.6C680.8 323.1 696.2 323.1 707.7 334.6L750 376.9C765.4 384.6 765.4 400 753.8 411.5Z",
143 "path": "M515.4 115.4C303.8 115.4 130.8 288.5 130.8 500 130.8 711.5 303.8 884.6 515.4 884.6S900 711.5 900 500C900 288.5 726.9 115.4 515.4 115.4ZM753.8 411.5L450 715.4C438.5 726.9 423.1 726.9 411.5 715.4L273.1 576.9C261.5 565.4 261.5 550 273.1 538.5L315.4 496.2C326.9 484.6 342.3 484.6 353.8 496.2L411.5 553.8C423.1 565.4 438.5 565.4 450 553.8L669.2 334.6C680.8 323.1 696.2 323.1 707.7 334.6L750 376.9C765.4 384.6 765.4 400 753.8 411.5Z",
144 "width": 1000
144 "width": 1000
145 },
145 },
146 "search": [
146 "search": [
147 "ok"
147 "ok"
148 ]
148 ]
149 },
149 },
150 {
150 {
151 "uid": "c158b3a004c055c6ad1471cd98932268",
151 "uid": "c158b3a004c055c6ad1471cd98932268",
152 "css": "down",
152 "css": "down",
153 "code": 59403,
153 "code": 59403,
154 "src": "custom_icons",
154 "src": "custom_icons",
155 "selected": true,
155 "selected": true,
156 "svg": {
156 "svg": {
157 "path": "M703.8 396.2L530.8 615.4C523.1 623.1 507.7 623.1 503.8 615.4L330.8 396.2C323.1 384.6 330.8 365.4 346.2 365.4H692.3C703.8 365.4 711.5 384.6 703.8 396.2Z",
157 "path": "M703.8 396.2L530.8 615.4C523.1 623.1 507.7 623.1 503.8 615.4L330.8 396.2C323.1 384.6 330.8 365.4 346.2 365.4H692.3C703.8 365.4 711.5 384.6 703.8 396.2Z",
158 "width": 1000
158 "width": 1000
159 },
159 },
160 "search": [
160 "search": [
161 "arrow_down"
161 "arrow_down"
162 ]
162 ]
163 },
163 },
164 {
164 {
165 "uid": "02f59f392ad28056845cfc04cb121f13",
165 "uid": "02f59f392ad28056845cfc04cb121f13",
166 "css": "comment",
166 "css": "comment",
167 "code": 59394,
167 "code": 59394,
168 "src": "custom_icons",
168 "src": "custom_icons",
169 "selected": true,
169 "selected": true,
170 "svg": {
170 "svg": {
171 "path": "M130.8 784.6V280.8C130.8 207.7 188.5 150 261.5 150H769.2C842.3 150 900 207.7 900 280.8V569.2C900 642.3 842.3 700 769.2 700H273.1C269.2 700 261.5 703.8 257.7 707.7L165.4 800C153.8 815.4 130.8 803.8 130.8 784.6ZM261.5 211.5C223.1 211.5 188.5 242.3 188.5 284.6V696.2L234.6 650C238.5 646.2 242.3 642.3 250 642.3H769.2C807.7 642.3 842.3 611.5 842.3 569.2V280.8C842.3 242.3 811.5 207.7 769.2 207.7H261.5Z",
171 "path": "M130.8 784.6V280.8C130.8 207.7 188.5 150 261.5 150H769.2C842.3 150 900 207.7 900 280.8V569.2C900 642.3 842.3 700 769.2 700H273.1C269.2 700 261.5 703.8 257.7 707.7L165.4 800C153.8 815.4 130.8 803.8 130.8 784.6ZM261.5 211.5C223.1 211.5 188.5 242.3 188.5 284.6V696.2L234.6 650C238.5 646.2 242.3 642.3 250 642.3H769.2C807.7 642.3 842.3 611.5 842.3 569.2V280.8C842.3 242.3 811.5 207.7 769.2 207.7H261.5Z",
172 "width": 1000
172 "width": 1000
173 },
173 },
174 "search": [
174 "search": [
175 "comment"
175 "comment"
176 ]
176 ]
177 },
177 },
178 {
178 {
179 "uid": "9a44b838872ca62b8aba7bbbbf67cc59",
179 "uid": "9a44b838872ca62b8aba7bbbbf67cc59",
180 "css": "feed",
180 "css": "feed",
181 "code": 59400,
181 "code": 59400,
182 "src": "custom_icons",
182 "src": "custom_icons",
183 "selected": true,
183 "selected": true,
184 "svg": {
184 "svg": {
185 "path": "M842.3 111.5H188.5C153.8 111.5 130.8 138.5 130.8 169.2V826.9C130.8 857.7 157.7 884.6 188.5 884.6H846.2C876.9 884.6 903.8 857.7 903.8 826.9V169.2C900 138.5 873.1 111.5 842.3 111.5ZM307.7 776.9C269.2 776.9 234.6 746.2 234.6 703.8S265.4 630.8 307.7 630.8C346.2 630.8 380.8 661.5 380.8 703.8S346.2 776.9 307.7 776.9ZM553.8 788.5C519.2 788.5 496.2 761.5 496.2 730.8 496.2 619.2 407.7 530.8 296.2 530.8 265.4 530.8 230.8 503.8 230.8 473.1 230.8 438.5 253.8 411.5 284.6 411.5L296.2 411.5C473.1 411.5 615.4 553.8 615.4 730.8 611.5 761.5 584.6 788.5 553.8 788.5ZM750 788.5C715.4 788.5 692.3 761.5 692.3 730.8 692.3 511.5 511.5 330.8 292.3 330.8 261.5 330.8 226.9 303.8 226.9 269.2 226.9 234.6 250 207.7 280.8 207.7L292.3 207.7C576.9 207.7 811.5 438.5 811.5 726.9 811.5 761.5 784.6 788.5 750 788.5Z",
185 "path": "M842.3 111.5H188.5C153.8 111.5 130.8 138.5 130.8 169.2V826.9C130.8 857.7 157.7 884.6 188.5 884.6H846.2C876.9 884.6 903.8 857.7 903.8 826.9V169.2C900 138.5 873.1 111.5 842.3 111.5ZM307.7 776.9C269.2 776.9 234.6 746.2 234.6 703.8S265.4 630.8 307.7 630.8C346.2 630.8 380.8 661.5 380.8 703.8S346.2 776.9 307.7 776.9ZM553.8 788.5C519.2 788.5 496.2 761.5 496.2 730.8 496.2 619.2 407.7 530.8 296.2 530.8 265.4 530.8 230.8 503.8 230.8 473.1 230.8 438.5 253.8 411.5 284.6 411.5L296.2 411.5C473.1 411.5 615.4 553.8 615.4 730.8 611.5 761.5 584.6 788.5 553.8 788.5ZM750 788.5C715.4 788.5 692.3 761.5 692.3 730.8 692.3 511.5 511.5 330.8 292.3 330.8 261.5 330.8 226.9 303.8 226.9 269.2 226.9 234.6 250 207.7 280.8 207.7L292.3 207.7C576.9 207.7 811.5 438.5 811.5 726.9 811.5 761.5 784.6 788.5 750 788.5Z",
186 "width": 1000
186 "width": 1000
187 },
187 },
188 "search": [
188 "search": [
189 "feed"
189 "feed"
190 ]
190 ]
191 },
191 },
192 {
192 {
193 "uid": "e0118d6f20b76d77317977ae8dc849d7",
193 "uid": "e0118d6f20b76d77317977ae8dc849d7",
194 "css": "left",
194 "css": "left",
195 "code": 59401,
195 "code": 59401,
196 "src": "custom_icons",
196 "src": "custom_icons",
197 "selected": true,
197 "selected": true,
198 "svg": {
198 "svg": {
199 "path": "M692.3 76.9L761.5 146.2C773.1 157.7 773.1 173.1 761.5 184.6L473.1 473.1C461.5 484.6 461.5 500 473.1 511.5L769.2 807.7C780.8 819.2 780.8 834.6 769.2 846.2L700 915.4C688.5 926.9 673.1 926.9 661.5 915.4L257.7 511.5C246.2 500 246.2 484.6 257.7 473.1L653.8 76.9C665.4 65.4 680.8 65.4 692.3 76.9Z",
199 "path": "M692.3 76.9L761.5 146.2C773.1 157.7 773.1 173.1 761.5 184.6L473.1 473.1C461.5 484.6 461.5 500 473.1 511.5L769.2 807.7C780.8 819.2 780.8 834.6 769.2 846.2L700 915.4C688.5 926.9 673.1 926.9 661.5 915.4L257.7 511.5C246.2 500 246.2 484.6 257.7 473.1L653.8 76.9C665.4 65.4 680.8 65.4 692.3 76.9Z",
200 "width": 1000
200 "width": 1000
201 },
201 },
202 "search": [
202 "search": [
203 "left"
203 "left"
204 ]
204 ]
205 },
205 },
206 {
206 {
207 "uid": "3cea97f90c8f2b0a90833855434f58de",
207 "uid": "3cea97f90c8f2b0a90833855434f58de",
208 "css": "right",
208 "css": "right",
209 "code": 59402,
209 "code": 59402,
210 "src": "custom_icons",
210 "src": "custom_icons",
211 "selected": true,
211 "selected": true,
212 "svg": {
212 "svg": {
213 "path": "M338.5 915.4L265.4 846.2C253.8 834.6 253.8 819.2 265.4 807.7L553.8 519.2C565.4 507.7 565.4 492.3 553.8 480.8L257.7 184.6C246.2 173.1 246.2 157.7 257.7 146.2L326.9 76.9C338.5 65.4 353.8 65.4 365.4 76.9L769.2 480.8C780.8 492.3 780.8 507.7 769.2 519.2L376.9 915.4C365.4 926.9 346.2 926.9 338.5 915.4Z",
213 "path": "M338.5 915.4L265.4 846.2C253.8 834.6 253.8 819.2 265.4 807.7L553.8 519.2C565.4 507.7 565.4 492.3 553.8 480.8L257.7 184.6C246.2 173.1 246.2 157.7 257.7 146.2L326.9 76.9C338.5 65.4 353.8 65.4 365.4 76.9L769.2 480.8C780.8 492.3 780.8 507.7 769.2 519.2L376.9 915.4C365.4 926.9 346.2 926.9 338.5 915.4Z",
214 "width": 1000
214 "width": 1000
215 },
215 },
216 "search": [
216 "search": [
217 "right"
217 "right"
218 ]
218 ]
219 },
219 },
220 {
220 {
221 "uid": "820a44cb2e7fc1d0e28b1d2a8cd44cb9",
221 "uid": "820a44cb2e7fc1d0e28b1d2a8cd44cb9",
222 "css": "git",
222 "css": "git",
223 "code": 59434,
223 "code": 59434,
224 "src": "custom_icons",
224 "src": "custom_icons",
225 "selected": true,
225 "selected": true,
226 "svg": {
226 "svg": {
227 "path": "M928.8 6.3H71.3C35 6.3 6.3 36.3 6.3 71.3V927.5C6.3 963.8 36.3 992.5 71.3 992.5H927.5C963.8 992.5 992.5 962.5 992.5 927.5V71.3C993.8 36.3 963.7 6.3 928.8 6.3ZM200 555C203.8 566.3 208.8 575 213.8 582.5 220 590 227.5 596.3 236.3 600 245 603.8 255 606.3 265 606.3 273.8 606.3 281.3 605 288.8 603.8 296.3 602.5 302.5 600 308.8 597.5L315 546.3H287.5C283.8 546.3 280 545 277.5 542.5 276.3 541.3 275 537.5 275 535L280 496.2H385L368.7 627.5C361.2 633.8 352.5 638.7 343.7 642.5 335 646.3 326.3 650 316.2 652.5 306.2 655 297.5 657.5 286.3 658.8 276.3 660 265 661.3 252.5 661.3 232.5 661.3 215 657.5 198.7 650 182.5 642.5 168.7 632.5 157.5 620 146.2 607.5 137.5 592.5 131.2 575 125 557.5 121.2 538.8 121.2 518.8 121.2 501.3 123.7 485 127.5 468.8 131.2 452.5 137.5 438.8 145 425 152.5 411.3 161.2 400 171.2 388.8 181.2 377.5 192.5 368.8 205 361.3 217.5 353.8 231.3 347.5 246.3 343.8 261.3 340 276.3 337.5 292.5 337.5 306.3 337.5 317.5 338.8 328.7 341.3 340 343.8 350 347.5 357.5 351.3 366.2 355 373.8 360 380 365 386.3 370 392.5 376.3 397.5 381.3L377.5 412.5C373.8 417.5 368.8 420 363.8 421.3 358.8 422.5 353.7 421.3 347.5 417.5 342.5 413.8 337.5 411.3 333.7 408.8 328.7 406.3 325 403.8 320 402.5 315 401.3 310 400 305 398.8 300 397.5 293.7 397.5 287.5 397.5 273.7 397.5 261.2 400 250 406.3 238.7 412.5 228.7 420 221.2 431.3 212.5 441.2 206.2 455 202.5 468.8 197.5 483.8 196.2 500 196.2 517.5 195 531.3 197.5 543.8 200 555ZM536.3 657.5H465L503.7 342.5H575L536.3 657.5ZM878.8 398.8H798.8L766.3 657.5H696.3L727.5 398.7H647.5L655 342.5H886.3L878.8 398.8Z",
227 "path": "M928.8 6.3H71.3C35 6.3 6.3 36.3 6.3 71.3V927.5C6.3 963.8 36.3 992.5 71.3 992.5H927.5C963.8 992.5 992.5 962.5 992.5 927.5V71.3C993.8 36.3 963.7 6.3 928.8 6.3ZM200 555C203.8 566.3 208.8 575 213.8 582.5 220 590 227.5 596.3 236.3 600 245 603.8 255 606.3 265 606.3 273.8 606.3 281.3 605 288.8 603.8 296.3 602.5 302.5 600 308.8 597.5L315 546.3H287.5C283.8 546.3 280 545 277.5 542.5 276.3 541.3 275 537.5 275 535L280 496.2H385L368.7 627.5C361.2 633.8 352.5 638.7 343.7 642.5 335 646.3 326.3 650 316.2 652.5 306.2 655 297.5 657.5 286.3 658.8 276.3 660 265 661.3 252.5 661.3 232.5 661.3 215 657.5 198.7 650 182.5 642.5 168.7 632.5 157.5 620 146.2 607.5 137.5 592.5 131.2 575 125 557.5 121.2 538.8 121.2 518.8 121.2 501.3 123.7 485 127.5 468.8 131.2 452.5 137.5 438.8 145 425 152.5 411.3 161.2 400 171.2 388.8 181.2 377.5 192.5 368.8 205 361.3 217.5 353.8 231.3 347.5 246.3 343.8 261.3 340 276.3 337.5 292.5 337.5 306.3 337.5 317.5 338.8 328.7 341.3 340 343.8 350 347.5 357.5 351.3 366.2 355 373.8 360 380 365 386.3 370 392.5 376.3 397.5 381.3L377.5 412.5C373.8 417.5 368.8 420 363.8 421.3 358.8 422.5 353.7 421.3 347.5 417.5 342.5 413.8 337.5 411.3 333.7 408.8 328.7 406.3 325 403.8 320 402.5 315 401.3 310 400 305 398.8 300 397.5 293.7 397.5 287.5 397.5 273.7 397.5 261.2 400 250 406.3 238.7 412.5 228.7 420 221.2 431.3 212.5 441.2 206.2 455 202.5 468.8 197.5 483.8 196.2 500 196.2 517.5 195 531.3 197.5 543.8 200 555ZM536.3 657.5H465L503.7 342.5H575L536.3 657.5ZM878.8 398.8H798.8L766.3 657.5H696.3L727.5 398.7H647.5L655 342.5H886.3L878.8 398.8Z",
228 "width": 1000
228 "width": 1000
229 },
229 },
230 "search": [
230 "search": [
231 "git"
231 "git"
232 ]
232 ]
233 },
233 },
234 {
234 {
235 "uid": "ea152b092f5ad7d610de2c388553e188",
235 "uid": "ea152b092f5ad7d610de2c388553e188",
236 "css": "hg",
236 "css": "hg",
237 "code": 59437,
237 "code": 59437,
238 "src": "custom_icons",
238 "src": "custom_icons",
239 "selected": true,
239 "selected": true,
240 "svg": {
240 "svg": {
241 "path": "M926.6 9.2H73.9C37.9 9.2 8.7 38.5 8.7 74.4V927.1C8.7 963.1 38 992.3 73.9 992.3H926.6C962.6 992.3 991.8 963 991.8 927.1V74.4C991.8 38.4 962.6 9.2 926.6 9.2ZM444 657.4H373.5L389.8 524.1H276.7L260.4 657.4H189.9L228.6 344.2H299.1L282.8 476.4H395.9L412.2 344.2H482.7L444 657.4ZM621 555.8C624.3 566.8 629.1 576 635.3 583.5 641.5 591 648.8 596.8 657.5 600.8 666.1 604.8 675.6 606.8 686.1 606.8 694.7 606.8 702.4 606 709.3 604.5 716.2 603 722.8 600.8 729.1 598.1L735.1 546.9H708.4C704.1 546.9 700.8 545.8 698.6 543.6 696.4 541.4 695.5 538.5 695.9 534.9L700.6 496.2H805.1L788.8 627.1C780.8 633 772.5 638.1 763.9 642.3 755.3 646.6 746.3 650 736.9 652.7 727.5 655.5 717.6 657.5 707.2 658.7 696.8 660 685.7 660.6 674 660.6 654.6 660.6 637 657 621 650 605 642.9 591.3 633.1 579.9 620.7 568.5 608.2 559.7 593.5 553.5 576.4 547.2 559.3 544.1 540.9 544.1 520.9 544.1 503.6 546.1 487.1 550 471.3 554 455.6 559.6 441.1 566.9 427.8 574.2 414.5 583 402.4 593.2 391.7 603.4 381 614.9 371.8 627.4 364.2 639.9 356.6 653.5 350.7 667.9 346.6 682.4 342.6 697.6 340.5 713.5 340.5 726.8 340.5 738.9 341.7 749.7 344.2 760.5 346.6 770.2 349.9 778.8 353.9 787.4 358 795.1 362.8 801.8 368.1 808.6 373.5 814.5 379 819.7 384.8L797 413.2C793.3 418.2 788.8 421.3 783.7 422.3 778.6 423.4 773.2 422.2 767.8 418.8 762.8 415.4 758.1 412.4 753.6 409.9 749.2 407.4 744.7 405.3 740.1 403.7 735.5 402 730.7 400.8 725.6 400 720.5 399.2 714.8 398.8 708.5 398.8 694.9 398.8 682.4 401.7 671.1 407.5 659.8 413.3 650 421.5 641.9 432 633.7 442.5 627.4 455.2 622.9 469.9 618.4 484.7 616.1 501 616.1 518.7 615.9 532.5 617.6 544.8 621 555.8Z",
241 "path": "M926.6 9.2H73.9C37.9 9.2 8.7 38.5 8.7 74.4V927.1C8.7 963.1 38 992.3 73.9 992.3H926.6C962.6 992.3 991.8 963 991.8 927.1V74.4C991.8 38.4 962.6 9.2 926.6 9.2ZM444 657.4H373.5L389.8 524.1H276.7L260.4 657.4H189.9L228.6 344.2H299.1L282.8 476.4H395.9L412.2 344.2H482.7L444 657.4ZM621 555.8C624.3 566.8 629.1 576 635.3 583.5 641.5 591 648.8 596.8 657.5 600.8 666.1 604.8 675.6 606.8 686.1 606.8 694.7 606.8 702.4 606 709.3 604.5 716.2 603 722.8 600.8 729.1 598.1L735.1 546.9H708.4C704.1 546.9 700.8 545.8 698.6 543.6 696.4 541.4 695.5 538.5 695.9 534.9L700.6 496.2H805.1L788.8 627.1C780.8 633 772.5 638.1 763.9 642.3 755.3 646.6 746.3 650 736.9 652.7 727.5 655.5 717.6 657.5 707.2 658.7 696.8 660 685.7 660.6 674 660.6 654.6 660.6 637 657 621 650 605 642.9 591.3 633.1 579.9 620.7 568.5 608.2 559.7 593.5 553.5 576.4 547.2 559.3 544.1 540.9 544.1 520.9 544.1 503.6 546.1 487.1 550 471.3 554 455.6 559.6 441.1 566.9 427.8 574.2 414.5 583 402.4 593.2 391.7 603.4 381 614.9 371.8 627.4 364.2 639.9 356.6 653.5 350.7 667.9 346.6 682.4 342.6 697.6 340.5 713.5 340.5 726.8 340.5 738.9 341.7 749.7 344.2 760.5 346.6 770.2 349.9 778.8 353.9 787.4 358 795.1 362.8 801.8 368.1 808.6 373.5 814.5 379 819.7 384.8L797 413.2C793.3 418.2 788.8 421.3 783.7 422.3 778.6 423.4 773.2 422.2 767.8 418.8 762.8 415.4 758.1 412.4 753.6 409.9 749.2 407.4 744.7 405.3 740.1 403.7 735.5 402 730.7 400.8 725.6 400 720.5 399.2 714.8 398.8 708.5 398.8 694.9 398.8 682.4 401.7 671.1 407.5 659.8 413.3 650 421.5 641.9 432 633.7 442.5 627.4 455.2 622.9 469.9 618.4 484.7 616.1 501 616.1 518.7 615.9 532.5 617.6 544.8 621 555.8Z",
242 "width": 1000
242 "width": 1000
243 },
243 },
244 "search": [
244 "search": [
245 "hg"
245 "hg"
246 ]
246 ]
247 },
247 },
248 {
248 {
249 "uid": "4a842c0afb4c35dacd21da71f9fed3f1",
249 "uid": "4a842c0afb4c35dacd21da71f9fed3f1",
250 "css": "comment-add",
250 "css": "comment-add",
251 "code": 59439,
251 "code": 59439,
252 "src": "custom_icons",
252 "src": "custom_icons",
253 "selected": true,
253 "selected": true,
254 "svg": {
254 "svg": {
255 "path": "M952.4 591.9V274.9C952.4 268.4 952.3 261.9 951.8 255.4 950.7 242.9 948.2 230.6 944.1 218.8 936.5 196.6 923.8 176.2 907.3 159.6 890.8 143.1 870.6 130.4 848.5 122.7 836.6 118.6 824.2 115.9 811.6 114.8 805.3 114.2 798.9 114.2 792.6 114.2H216.9C204 114.2 191.3 114.1 178.5 116 166.3 117.9 154.4 121.2 143 125.9 121.4 134.8 101.9 148.7 86.4 166.2 70.8 183.8 59.3 205 53.1 227.7 49.7 240.1 47.9 252.8 47.6 265.6 47.3 278.7 47.6 291.8 47.6 304.9V861.8C47.6 870.7 52.5 878.6 60.5 882.5 67.3 885.9 75.6 886.2 82.4 882.7 84.8 881.5 86.9 879.7 88.8 877.8 91.1 875.5 93.4 873.2 95.6 871 100.3 866.3 105 861.6 109.7 856.9L137.9 828.6C147.3 819.2 156.6 809.9 166 800.5 175.2 791.3 184.6 782.1 193.7 772.7 197.7 768.5 201.9 764.4 207.6 762.7 210.4 761.9 213.2 761.8 216 761.8H782.7C795.5 761.8 808.3 762 821 760.1 844.8 756.5 867.7 747.3 887.3 733.3 906.2 719.9 922.1 702.1 933.2 681.8 945.1 660.2 951.5 636 952.2 611.4 952.5 604.9 952.4 598.4 952.4 591.9ZM883.4 285.1V602.5C883.4 608.8 883.4 615.1 882.5 621.4 881.7 627.5 880.2 633.6 878.1 639.4 874.4 649.4 868.8 658.7 861.7 666.7 846.6 683.6 825.1 693.8 802.5 695.1 796.3 695.4 790 695.2 783.8 695.2H207.8C201.2 695.2 194.7 695.2 188.1 695.2 185 695.2 181.8 695.2 178.8 696.1 176.2 696.9 173.9 698.2 171.8 699.9 169.6 701.7 167.6 703.7 165.6 705.7 163.3 708 161 710.3 158.7 712.6 154 717.3 149.4 721.9 144.7 726.6 135.3 736 126 745.3 116.6 754.7V270C116.6 257.8 118.8 245.7 123.7 234.6 128 224.9 134 215.9 141.5 208.4 157.5 192.4 179.6 183.3 202.2 183.3H791.5C797.6 183.3 803.7 183.3 809.7 184.2 832 187.4 852.4 199.4 866 217.4 872.8 226.4 877.7 236.7 880.5 247.6 882 253.5 882.9 259.6 883.1 265.8 883.6 272.2 883.4 278.7 883.4 285.1ZM668.8 402H538.2C534.4 402 526.7 394.3 526.7 390.5V263.7C526.7 256 519 248.3 515.2 248.3H465.3C457.6 248.3 449.9 256 449.9 259.8V390.4C449.9 394.2 442.2 401.9 438.4 401.9H311.7C304 401.9 296.3 409.6 296.3 413.4V463.3C296.3 471 304 478.7 307.8 478.7H434.5C442.2 478.7 449.9 486.4 449.9 490.2V617C449.9 624.7 457.6 632.4 461.4 632.4H511.3C519 632.4 526.7 624.7 526.7 620.9V494.1C526.7 486.4 534.4 478.7 538.2 478.7H665C672.7 478.7 680.4 471 680.4 467.2V417.3C680.3 409.6 672.6 402 668.8 402Z",
255 "path": "M952.4 591.9V274.9C952.4 268.4 952.3 261.9 951.8 255.4 950.7 242.9 948.2 230.6 944.1 218.8 936.5 196.6 923.8 176.2 907.3 159.6 890.8 143.1 870.6 130.4 848.5 122.7 836.6 118.6 824.2 115.9 811.6 114.8 805.3 114.2 798.9 114.2 792.6 114.2H216.9C204 114.2 191.3 114.1 178.5 116 166.3 117.9 154.4 121.2 143 125.9 121.4 134.8 101.9 148.7 86.4 166.2 70.8 183.8 59.3 205 53.1 227.7 49.7 240.1 47.9 252.8 47.6 265.6 47.3 278.7 47.6 291.8 47.6 304.9V861.8C47.6 870.7 52.5 878.6 60.5 882.5 67.3 885.9 75.6 886.2 82.4 882.7 84.8 881.5 86.9 879.7 88.8 877.8 91.1 875.5 93.4 873.2 95.6 871 100.3 866.3 105 861.6 109.7 856.9L137.9 828.6C147.3 819.2 156.6 809.9 166 800.5 175.2 791.3 184.6 782.1 193.7 772.7 197.7 768.5 201.9 764.4 207.6 762.7 210.4 761.9 213.2 761.8 216 761.8H782.7C795.5 761.8 808.3 762 821 760.1 844.8 756.5 867.7 747.3 887.3 733.3 906.2 719.9 922.1 702.1 933.2 681.8 945.1 660.2 951.5 636 952.2 611.4 952.5 604.9 952.4 598.4 952.4 591.9ZM883.4 285.1V602.5C883.4 608.8 883.4 615.1 882.5 621.4 881.7 627.5 880.2 633.6 878.1 639.4 874.4 649.4 868.8 658.7 861.7 666.7 846.6 683.6 825.1 693.8 802.5 695.1 796.3 695.4 790 695.2 783.8 695.2H207.8C201.2 695.2 194.7 695.2 188.1 695.2 185 695.2 181.8 695.2 178.8 696.1 176.2 696.9 173.9 698.2 171.8 699.9 169.6 701.7 167.6 703.7 165.6 705.7 163.3 708 161 710.3 158.7 712.6 154 717.3 149.4 721.9 144.7 726.6 135.3 736 126 745.3 116.6 754.7V270C116.6 257.8 118.8 245.7 123.7 234.6 128 224.9 134 215.9 141.5 208.4 157.5 192.4 179.6 183.3 202.2 183.3H791.5C797.6 183.3 803.7 183.3 809.7 184.2 832 187.4 852.4 199.4 866 217.4 872.8 226.4 877.7 236.7 880.5 247.6 882 253.5 882.9 259.6 883.1 265.8 883.6 272.2 883.4 278.7 883.4 285.1ZM668.8 402H538.2C534.4 402 526.7 394.3 526.7 390.5V263.7C526.7 256 519 248.3 515.2 248.3H465.3C457.6 248.3 449.9 256 449.9 259.8V390.4C449.9 394.2 442.2 401.9 438.4 401.9H311.7C304 401.9 296.3 409.6 296.3 413.4V463.3C296.3 471 304 478.7 307.8 478.7H434.5C442.2 478.7 449.9 486.4 449.9 490.2V617C449.9 624.7 457.6 632.4 461.4 632.4H511.3C519 632.4 526.7 624.7 526.7 620.9V494.1C526.7 486.4 534.4 478.7 538.2 478.7H665C672.7 478.7 680.4 471 680.4 467.2V417.3C680.3 409.6 672.6 402 668.8 402Z",
256 "width": 1000
256 "width": 1000
257 },
257 },
258 "search": [
258 "search": [
259 "comment-add"
259 "comment-add"
260 ]
260 ]
261 },
261 },
262 {
262 {
263 "uid": "2427f6b8d4379b9a0b41cf31780807cf",
263 "uid": "2427f6b8d4379b9a0b41cf31780807cf",
264 "css": "comment-toggle",
264 "css": "comment-toggle",
265 "code": 59440,
265 "code": 59440,
266 "src": "custom_icons",
266 "src": "custom_icons",
267 "selected": true,
267 "selected": true,
268 "svg": {
268 "svg": {
269 "path": "M797.6 114.2H202.4C116.6 114.2 47.6 183.3 47.6 269V861.9C47.6 881.4 69.5 891.1 84.1 881.8 86.4 880.7 88.6 879.1 90.6 877.1L199.8 768C202.1 765.7 204.7 764 207.7 762.8 209.7 762.2 211.9 761.9 214.3 761.9H797.6C883.4 761.9 952.4 692.8 952.4 607.1V269C952.4 183.2 883.3 114.2 797.6 114.2ZM118.3 752.6V269.5C118.3 222.5 156.4 184.3 203.5 184.3H680.1C593.7 267.9 175.5 695.4 171.4 699.5L118.3 752.6Z",
269 "path": "M797.6 114.2H202.4C116.6 114.2 47.6 183.3 47.6 269V861.9C47.6 881.4 69.5 891.1 84.1 881.8 86.4 880.7 88.6 879.1 90.6 877.1L199.8 768C202.1 765.7 204.7 764 207.7 762.8 209.7 762.2 211.9 761.9 214.3 761.9H797.6C883.4 761.9 952.4 692.8 952.4 607.1V269C952.4 183.2 883.3 114.2 797.6 114.2ZM118.3 752.6V269.5C118.3 222.5 156.4 184.3 203.5 184.3H680.1C593.7 267.9 175.5 695.4 171.4 699.5L118.3 752.6Z",
270 "width": 1000
270 "width": 1000
271 },
271 },
272 "search": [
272 "search": [
273 "comment-toggle"
273 "comment-toggle"
274 ]
274 ]
275 },
275 },
276 {
276 {
277 "uid": "6533bdc16ab201eb3f3b27ce989cab33",
277 "uid": "6533bdc16ab201eb3f3b27ce989cab33",
278 "css": "folder-open-empty",
278 "css": "folder-open-empty",
279 "code": 61717,
279 "code": 61717,
280 "src": "fontawesome"
280 "src": "fontawesome"
281 },
281 },
282 {
282 {
283 "uid": "d64b34fac1d9923b7d29d1550b628ecd",
283 "uid": "d64b34fac1d9923b7d29d1550b628ecd",
284 "css": "lock",
284 "css": "lock",
285 "code": 59398,
285 "code": 59398,
286 "src": "custom_icons",
286 "src": "custom_icons",
287 "selected": true,
287 "selected": true,
288 "svg": {
288 "svg": {
289 "path": "M812.5 424.1H758.9V317C758.9 308 758.9 303.6 758.9 299.1 758.9 294.6 758.9 290.2 758.9 285.7 758.9 281.3 758.9 281.3 758.9 276.8 758.9 267.9 758.9 263.4 754.5 254.5 754.5 250 754.5 250 750 245.5 750 236.6 745.5 232.1 741.1 223.2 741.1 223.2 741.1 218.8 736.6 218.8 732.1 209.8 727.7 200.9 723.2 192 723.2 192 718.8 187.5 718.8 187.5 723.2 178.6 718.8 169.6 714.3 165.2 714.3 160.7 709.8 160.7 709.8 156.3 705.4 151.8 700.9 142.9 696.4 138.4 696.4 138.4 692 133.9 692 133.9 683 125 678.6 120.5 669.6 111.6 669.6 111.6 665.2 111.6 665.2 107.1 660.7 102.7 651.8 98.2 642.9 93.8 638.4 93.8 638.4 89.3 633.9 89.3 629.5 84.8 620.5 80.4 616.1 80.4 611.6 80.4 611.6 75.9 607.1 75.9 598.2 71.4 589.3 67 580.4 67 580.4 67 580.4 67 580.4 67 571.4 62.5 562.5 62.5 549.1 58 544.6 58 544.6 58 540.2 58 535.7 58 535.7 58 531.3 58 531.3 58 526.8 58 526.8 58 526.8 58 522.3 58 522.3 58 522.3 58 522.3 58 522.3 58 522.3 58 522.3 58 522.3 58 517.9 58 513.4 58 513.4 58 513.4 58 508.9 58 508.9 58 504.5 58 504.5 58 500 58 500 58 500 58 500 58 495.5 58 491.1 58 491.1 58 491.1 58 491.1 58 491.1 58 491.1 58 491.1 58 491.1 58 491.1 58 486.6 58 486.6 58 486.6 58 482.1 58 482.1 58 477.7 58 477.7 58 473.2 58 468.8 58 468.8 58 464.3 58 455.4 58 442 62.5 433 67 433 67 433 67 433 67 410.7 67 397.3 71.4 388.4 75.9 383.9 75.9 383.9 80.4 379.5 80.4 375 84.8 370.5 84.8 361.6 89.3 361.6 93.8 357.1 93.8 357.1 93.8 348.2 98.2 339.3 102.7 334.8 111.6 334.8 111.6 330.4 111.6 330.4 116.1 321.4 120.5 317 125 308 133.9 308 133.9 303.6 138.4 303.6 138.4 299.1 142.9 294.6 151.8 290.2 156.3 290.2 160.7 285.7 160.7 285.7 165.2 276.8 169.6 272.3 178.6 272.3 183 267.9 183 267.9 187.5 267.9 187.5 263.4 196.4 258.9 205.4 254.5 214.3 254.5 214.3 254.5 218.8 250 218.8 250 232.1 245.5 236.6 245.5 245.5 245.5 250 245.5 250 241.1 254.5 241.1 263.4 236.6 267.9 236.6 276.8 236.6 281.3 236.6 281.3 236.6 285.7 236.6 290.2 236.6 294.6 236.6 299.1 236.6 303.6 236.6 312.5 236.6 317V424.1H187.5C169.6 424.1 160.7 437.5 160.7 450.9V915.2C160.7 933 174.1 942 187.5 942H808C825.9 942 834.8 928.6 834.8 915.2V450.9C839.3 433 825.9 424.1 812.5 424.1ZM361.6 317C361.6 250 410.7 196.4 473.2 183 473.2 183 473.2 183 477.7 183 486.6 183 491.1 183 500 183 500 183 504.5 183 504.5 183 504.5 183 504.5 183 504.5 183 513.4 183 517.9 183 526.8 183 526.8 183 526.8 183 531.3 183 593.8 196.4 642.9 250 642.9 317V424.1H361.6V317Z",
289 "path": "M812.5 424.1H758.9V317C758.9 308 758.9 303.6 758.9 299.1 758.9 294.6 758.9 290.2 758.9 285.7 758.9 281.3 758.9 281.3 758.9 276.8 758.9 267.9 758.9 263.4 754.5 254.5 754.5 250 754.5 250 750 245.5 750 236.6 745.5 232.1 741.1 223.2 741.1 223.2 741.1 218.8 736.6 218.8 732.1 209.8 727.7 200.9 723.2 192 723.2 192 718.8 187.5 718.8 187.5 723.2 178.6 718.8 169.6 714.3 165.2 714.3 160.7 709.8 160.7 709.8 156.3 705.4 151.8 700.9 142.9 696.4 138.4 696.4 138.4 692 133.9 692 133.9 683 125 678.6 120.5 669.6 111.6 669.6 111.6 665.2 111.6 665.2 107.1 660.7 102.7 651.8 98.2 642.9 93.8 638.4 93.8 638.4 89.3 633.9 89.3 629.5 84.8 620.5 80.4 616.1 80.4 611.6 80.4 611.6 75.9 607.1 75.9 598.2 71.4 589.3 67 580.4 67 580.4 67 580.4 67 580.4 67 571.4 62.5 562.5 62.5 549.1 58 544.6 58 544.6 58 540.2 58 535.7 58 535.7 58 531.3 58 531.3 58 526.8 58 526.8 58 526.8 58 522.3 58 522.3 58 522.3 58 522.3 58 522.3 58 522.3 58 522.3 58 522.3 58 517.9 58 513.4 58 513.4 58 513.4 58 508.9 58 508.9 58 504.5 58 504.5 58 500 58 500 58 500 58 500 58 495.5 58 491.1 58 491.1 58 491.1 58 491.1 58 491.1 58 491.1 58 491.1 58 491.1 58 491.1 58 486.6 58 486.6 58 486.6 58 482.1 58 482.1 58 477.7 58 477.7 58 473.2 58 468.8 58 468.8 58 464.3 58 455.4 58 442 62.5 433 67 433 67 433 67 433 67 410.7 67 397.3 71.4 388.4 75.9 383.9 75.9 383.9 80.4 379.5 80.4 375 84.8 370.5 84.8 361.6 89.3 361.6 93.8 357.1 93.8 357.1 93.8 348.2 98.2 339.3 102.7 334.8 111.6 334.8 111.6 330.4 111.6 330.4 116.1 321.4 120.5 317 125 308 133.9 308 133.9 303.6 138.4 303.6 138.4 299.1 142.9 294.6 151.8 290.2 156.3 290.2 160.7 285.7 160.7 285.7 165.2 276.8 169.6 272.3 178.6 272.3 183 267.9 183 267.9 187.5 267.9 187.5 263.4 196.4 258.9 205.4 254.5 214.3 254.5 214.3 254.5 218.8 250 218.8 250 232.1 245.5 236.6 245.5 245.5 245.5 250 245.5 250 241.1 254.5 241.1 263.4 236.6 267.9 236.6 276.8 236.6 281.3 236.6 281.3 236.6 285.7 236.6 290.2 236.6 294.6 236.6 299.1 236.6 303.6 236.6 312.5 236.6 317V424.1H187.5C169.6 424.1 160.7 437.5 160.7 450.9V915.2C160.7 933 174.1 942 187.5 942H808C825.9 942 834.8 928.6 834.8 915.2V450.9C839.3 433 825.9 424.1 812.5 424.1ZM361.6 317C361.6 250 410.7 196.4 473.2 183 473.2 183 473.2 183 477.7 183 486.6 183 491.1 183 500 183 500 183 504.5 183 504.5 183 504.5 183 504.5 183 504.5 183 513.4 183 517.9 183 526.8 183 526.8 183 526.8 183 531.3 183 593.8 196.4 642.9 250 642.9 317V424.1H361.6V317Z",
290 "width": 1000
290 "width": 1000
291 },
291 },
292 "search": [
292 "search": [
293 "lock"
293 "lock"
294 ]
294 ]
295 },
295 },
296 {
296 {
297 "uid": "d95fde5e3bfeb3302efc47c90538a1c5",
297 "uid": "d95fde5e3bfeb3302efc47c90538a1c5",
298 "css": "more",
298 "css": "more",
299 "code": 59410,
299 "code": 59410,
300 "src": "custom_icons",
300 "src": "custom_icons",
301 "selected": true,
301 "selected": true,
302 "svg": {
302 "svg": {
303 "path": "M546.2 415.4H446.2C430.8 415.4 419.2 426.9 419.2 442.3V542.3C419.2 557.7 430.8 569.2 446.2 569.2H546.2C561.5 569.2 573.1 557.7 573.1 542.3V442.3C573.1 426.9 561.5 415.4 546.2 415.4ZM546.2 107.7H446.2C430.8 107.7 419.2 119.2 419.2 134.6V234.6C419.2 250 430.8 261.5 446.2 261.5H546.2C561.5 261.5 573.1 250 573.1 234.6V134.6C573.1 119.2 561.5 107.7 546.2 107.7ZM546.2 723.1H446.2C430.8 723.1 419.2 734.6 419.2 750V850C419.2 865.4 430.8 876.9 446.2 876.9H546.2C561.5 876.9 573.1 865.4 573.1 850V750C573.1 734.6 561.5 723.1 546.2 723.1Z",
303 "path": "M546.2 415.4H446.2C430.8 415.4 419.2 426.9 419.2 442.3V542.3C419.2 557.7 430.8 569.2 446.2 569.2H546.2C561.5 569.2 573.1 557.7 573.1 542.3V442.3C573.1 426.9 561.5 415.4 546.2 415.4ZM546.2 107.7H446.2C430.8 107.7 419.2 119.2 419.2 134.6V234.6C419.2 250 430.8 261.5 446.2 261.5H546.2C561.5 261.5 573.1 250 573.1 234.6V134.6C573.1 119.2 561.5 107.7 546.2 107.7ZM546.2 723.1H446.2C430.8 723.1 419.2 734.6 419.2 750V850C419.2 865.4 430.8 876.9 446.2 876.9H546.2C561.5 876.9 573.1 865.4 573.1 850V750C573.1 734.6 561.5 723.1 546.2 723.1Z",
304 "width": 1000
304 "width": 1000
305 },
305 },
306 "search": [
306 "search": [
307 "more"
307 "more"
308 ]
308 ]
309 },
309 },
310 {
310 {
311 "uid": "34e7772638ae3ca1bfb0a4eca2c39221",
311 "uid": "34e7772638ae3ca1bfb0a4eca2c39221",
312 "css": "merge",
312 "css": "merge",
313 "code": 59443,
313 "code": 59443,
314 "src": "custom_icons",
314 "src": "custom_icons",
315 "selected": true,
315 "selected": true,
316 "svg": {
316 "svg": {
317 "path": "M199.8 740.5C199.8 812.2 258.1 870.5 329.8 870.5S459.8 812.2 459.8 740.5C459.8 694.6 435.8 654.5 399.8 631.3 418.4 491.7 533.4 451.9 602.4 440.6V742.4C563.7 765 537.4 806.4 537.4 854.4 537.4 926.1 595.7 984.4 667.4 984.4S797.4 926.1 797.4 854.4C797.4 806.5 771.1 765 732.4 742.4V254.9C771.1 232.3 797.4 190.9 797.4 142.9 797.4 71.2 739.1 12.9 667.4 12.9S537.4 71.2 537.4 142.9C537.4 190.8 563.7 232.3 602.4 254.9V309.9C542.2 317.8 440.4 342.3 364.2 417.8 309.5 472.1 277.9 542.1 269.6 625.9 228.4 647.7 199.8 690.6 199.8 740.5ZM667.6 897.8C643.7 897.8 624.3 878.3 624.3 854.5S643.8 811.2 667.6 811.2C691.5 811.2 710.9 830.7 710.9 854.5S691.5 897.8 667.6 897.8ZM667.6 99.6C691.5 99.6 710.9 119 710.9 142.9S691.4 186.2 667.6 186.2C643.7 186.2 624.3 166.8 624.3 142.9S643.7 99.6 667.6 99.6ZM329.9 783.9C306 783.9 286.6 764.4 286.6 740.6S306.1 697.3 329.9 697.3C353.8 697.3 373.2 716.7 373.2 740.6S353.8 783.9 329.9 783.9Z",
317 "path": "M199.8 740.5C199.8 812.2 258.1 870.5 329.8 870.5S459.8 812.2 459.8 740.5C459.8 694.6 435.8 654.5 399.8 631.3 418.4 491.7 533.4 451.9 602.4 440.6V742.4C563.7 765 537.4 806.4 537.4 854.4 537.4 926.1 595.7 984.4 667.4 984.4S797.4 926.1 797.4 854.4C797.4 806.5 771.1 765 732.4 742.4V254.9C771.1 232.3 797.4 190.9 797.4 142.9 797.4 71.2 739.1 12.9 667.4 12.9S537.4 71.2 537.4 142.9C537.4 190.8 563.7 232.3 602.4 254.9V309.9C542.2 317.8 440.4 342.3 364.2 417.8 309.5 472.1 277.9 542.1 269.6 625.9 228.4 647.7 199.8 690.6 199.8 740.5ZM667.6 897.8C643.7 897.8 624.3 878.3 624.3 854.5S643.8 811.2 667.6 811.2C691.5 811.2 710.9 830.7 710.9 854.5S691.5 897.8 667.6 897.8ZM667.6 99.6C691.5 99.6 710.9 119 710.9 142.9S691.4 186.2 667.6 186.2C643.7 186.2 624.3 166.8 624.3 142.9S643.7 99.6 667.6 99.6ZM329.9 783.9C306 783.9 286.6 764.4 286.6 740.6S306.1 697.3 329.9 697.3C353.8 697.3 373.2 716.7 373.2 740.6S353.8 783.9 329.9 783.9Z",
318 "width": 1000
318 "width": 1000
319 },
319 },
320 "search": [
320 "search": [
321 "merge"
321 "merge"
322 ]
322 ]
323 },
323 },
324 {
324 {
325 "uid": "c95735c17a10af81448c7fed98a04546",
325 "uid": "c95735c17a10af81448c7fed98a04546",
326 "css": "folder-open",
326 "css": "folder-open",
327 "code": 59405,
327 "code": 59405,
328 "src": "fontawesome"
328 "src": "fontawesome"
329 },
329 },
330 {
330 {
331 "uid": "865ac833a8efcfc24a6f573705ce56b1",
331 "uid": "865ac833a8efcfc24a6f573705ce56b1",
332 "css": "svn",
332 "css": "svn",
333 "code": 59438,
333 "code": 59438,
334 "src": "custom_icons",
334 "src": "custom_icons",
335 "selected": true,
335 "selected": true,
336 "svg": {
336 "svg": {
337 "path": "M933.4 9.2H80.7C44.7 9.2 15.5 38.5 15.5 74.4V927.1C15.5 963.1 44.8 992.3 80.7 992.3H933.4C969.4 992.3 998.6 963 998.6 927.1V74.4C998.7 38.4 969.4 9.2 933.4 9.2ZM167.9 447.1C171.1 451 175.4 454.4 180.8 457.3 186.2 460.2 192.2 463 199 465.4 205.7 467.8 212.7 470.5 219.8 473.3 226.9 476.2 233.9 479.5 240.7 483.2 247.5 486.9 253.6 491.6 259 497.2 264.4 502.8 268.7 509.6 271.9 517.4 275.1 525.3 276.8 534.8 276.8 545.8 276.8 561.6 274.1 576.4 268.6 590.3 263.1 604.3 255.3 616.4 245.1 626.8 234.9 637.2 222.5 645.4 208 651.5 193.4 657.6 177 660.7 158.8 660.7 149.7 660.7 140.7 659.7 131.5 657.7S113.6 652.8 105.2 649.2C96.8 645.5 89 641.2 81.8 636.2 74.6 631.2 68.5 625.6 63.5 619.5L88.5 586.7C90.5 584.3 93 582.3 95.9 580.7 98.8 579.1 101.8 578.3 104.8 578.3 108.8 578.3 112.7 579.7 116.5 582.5 120.3 585.3 124.5 588.4 129.1 591.8 133.7 595.2 139 598.2 145.1 601.1 151.2 603.9 158.7 605.3 167.6 605.3 180.7 605.3 190.7 601.7 197.8 594.7 204.9 587.6 208.4 577.1 208.4 563.2 208.4 556.8 206.8 551.4 203.5 547.3 200.3 543.1 196 539.7 190.8 536.8 185.6 533.9 179.6 531.4 172.8 529.1 166 526.9 159.2 524.5 152.1 521.9 145.1 519.3 138.2 516.2 131.4 512.8 124.6 509.3 118.6 504.7 113.4 499 108.2 493.3 103.9 486.4 100.7 478.2 97.5 469.9 95.9 459.8 95.9 447.7 95.9 433.8 98.5 420.4 103.7 407.6 108.9 394.8 116.4 383.4 126.2 373.5 136 363.6 147.8 355.7 161.7 349.8 175.6 343.9 191.3 341 208.6 341 217.5 341 226.1 341.9 234.5 343.8S250.8 348.2 258.1 351.6C265.4 354.9 272.1 358.8 278.1 363.3 284.1 367.8 289.2 372.8 293.4 378.1L272.3 407C269.7 410.3 267.2 412.8 264.8 414.4 262.4 416 259.4 416.8 256 416.8 252.7 416.8 249.4 415.8 246.1 413.6 242.8 411.4 239.1 409.1 235 406.5 230.9 403.9 226.2 401.6 220.9 399.4 215.6 397.2 209.3 396.2 202.2 396.2 195.6 396.2 189.8 397.1 184.9 399 179.9 400.9 175.8 403.4 172.5 406.8 169.2 410.1 166.7 414 165.1 418.4 163.5 422.9 162.6 427.8 162.6 433 163.1 438.4 164.7 443.2 167.9 447.1ZM480 657.4H416.3L339.2 343.7H395.6C401.6 343.7 406.4 345.1 410 348 413.6 350.8 415.8 354.5 416.7 359L449.4 531.8C451.3 538.7 453 546.3 454.6 554.8 456.2 563.2 457.5 571.9 458.7 581 461.7 572 464.9 563.2 468.4 554.8 471.8 546.4 475.4 538.8 479.2 531.8L552.3 359C553.2 357.1 554.4 355.2 556.1 353.4 557.7 351.5 559.6 349.8 561.8 348.4 564 347 566.4 345.8 569 345 571.6 344.2 574.4 343.7 577.3 343.7H634.1L480 657.4ZM902.6 657.4H866C860.5 657.4 856.1 656.5 852.8 654.7 849.4 652.9 846.2 649.9 843.2 645.8L733.6 452.2C733.3 456.2 733 460.1 732.7 463.8 732.3 467.6 732 471.1 731.7 474.4L710.2 657.4H648.2L686.9 343.7H723.9C726.9 343.7 729.5 343.8 731.6 344 733.7 344.2 735.5 344.7 737.1 345.5 738.7 346.3 740.1 347.4 741.4 348.8S744.1 352.1 745.5 354.4L855.5 548.1C855.8 543.1 856.2 538.3 856.7 533.7 857.2 529.2 857.8 524.8 858.3 520.8L879.4 343.6H941.4L902.6 657.4Z",
337 "path": "M933.4 9.2H80.7C44.7 9.2 15.5 38.5 15.5 74.4V927.1C15.5 963.1 44.8 992.3 80.7 992.3H933.4C969.4 992.3 998.6 963 998.6 927.1V74.4C998.7 38.4 969.4 9.2 933.4 9.2ZM167.9 447.1C171.1 451 175.4 454.4 180.8 457.3 186.2 460.2 192.2 463 199 465.4 205.7 467.8 212.7 470.5 219.8 473.3 226.9 476.2 233.9 479.5 240.7 483.2 247.5 486.9 253.6 491.6 259 497.2 264.4 502.8 268.7 509.6 271.9 517.4 275.1 525.3 276.8 534.8 276.8 545.8 276.8 561.6 274.1 576.4 268.6 590.3 263.1 604.3 255.3 616.4 245.1 626.8 234.9 637.2 222.5 645.4 208 651.5 193.4 657.6 177 660.7 158.8 660.7 149.7 660.7 140.7 659.7 131.5 657.7S113.6 652.8 105.2 649.2C96.8 645.5 89 641.2 81.8 636.2 74.6 631.2 68.5 625.6 63.5 619.5L88.5 586.7C90.5 584.3 93 582.3 95.9 580.7 98.8 579.1 101.8 578.3 104.8 578.3 108.8 578.3 112.7 579.7 116.5 582.5 120.3 585.3 124.5 588.4 129.1 591.8 133.7 595.2 139 598.2 145.1 601.1 151.2 603.9 158.7 605.3 167.6 605.3 180.7 605.3 190.7 601.7 197.8 594.7 204.9 587.6 208.4 577.1 208.4 563.2 208.4 556.8 206.8 551.4 203.5 547.3 200.3 543.1 196 539.7 190.8 536.8 185.6 533.9 179.6 531.4 172.8 529.1 166 526.9 159.2 524.5 152.1 521.9 145.1 519.3 138.2 516.2 131.4 512.8 124.6 509.3 118.6 504.7 113.4 499 108.2 493.3 103.9 486.4 100.7 478.2 97.5 469.9 95.9 459.8 95.9 447.7 95.9 433.8 98.5 420.4 103.7 407.6 108.9 394.8 116.4 383.4 126.2 373.5 136 363.6 147.8 355.7 161.7 349.8 175.6 343.9 191.3 341 208.6 341 217.5 341 226.1 341.9 234.5 343.8S250.8 348.2 258.1 351.6C265.4 354.9 272.1 358.8 278.1 363.3 284.1 367.8 289.2 372.8 293.4 378.1L272.3 407C269.7 410.3 267.2 412.8 264.8 414.4 262.4 416 259.4 416.8 256 416.8 252.7 416.8 249.4 415.8 246.1 413.6 242.8 411.4 239.1 409.1 235 406.5 230.9 403.9 226.2 401.6 220.9 399.4 215.6 397.2 209.3 396.2 202.2 396.2 195.6 396.2 189.8 397.1 184.9 399 179.9 400.9 175.8 403.4 172.5 406.8 169.2 410.1 166.7 414 165.1 418.4 163.5 422.9 162.6 427.8 162.6 433 163.1 438.4 164.7 443.2 167.9 447.1ZM480 657.4H416.3L339.2 343.7H395.6C401.6 343.7 406.4 345.1 410 348 413.6 350.8 415.8 354.5 416.7 359L449.4 531.8C451.3 538.7 453 546.3 454.6 554.8 456.2 563.2 457.5 571.9 458.7 581 461.7 572 464.9 563.2 468.4 554.8 471.8 546.4 475.4 538.8 479.2 531.8L552.3 359C553.2 357.1 554.4 355.2 556.1 353.4 557.7 351.5 559.6 349.8 561.8 348.4 564 347 566.4 345.8 569 345 571.6 344.2 574.4 343.7 577.3 343.7H634.1L480 657.4ZM902.6 657.4H866C860.5 657.4 856.1 656.5 852.8 654.7 849.4 652.9 846.2 649.9 843.2 645.8L733.6 452.2C733.3 456.2 733 460.1 732.7 463.8 732.3 467.6 732 471.1 731.7 474.4L710.2 657.4H648.2L686.9 343.7H723.9C726.9 343.7 729.5 343.8 731.6 344 733.7 344.2 735.5 344.7 737.1 345.5 738.7 346.3 740.1 347.4 741.4 348.8S744.1 352.1 745.5 354.4L855.5 548.1C855.8 543.1 856.2 538.3 856.7 533.7 857.2 529.2 857.8 524.8 858.3 520.8L879.4 343.6H941.4L902.6 657.4Z",
338 "width": 1000
338 "width": 1000
339 },
339 },
340 "search": [
340 "search": [
341 "svn"
341 "svn"
342 ]
342 ]
343 },
343 },
344 {
344 {
345 "uid": "bbfb51903f40597f0b70fd75bc7b5cac",
345 "uid": "bbfb51903f40597f0b70fd75bc7b5cac",
346 "css": "trash",
346 "css": "trash",
347 "code": 61944,
347 "code": 61944,
348 "src": "fontawesome"
348 "src": "fontawesome"
349 },
349 },
350 {
350 {
351 "uid": "f48ae54adfb27d8ada53d0fd9e34ee10",
351 "uid": "f48ae54adfb27d8ada53d0fd9e34ee10",
352 "css": "trash-empty",
352 "css": "trash-empty",
353 "code": 59406,
353 "code": 59406,
354 "src": "fontawesome"
354 "src": "fontawesome"
355 },
355 },
356 {
356 {
357 "uid": "f8aa663c489bcbd6e68ec8147dca841e",
357 "uid": "f8aa663c489bcbd6e68ec8147dca841e",
358 "css": "folder",
358 "css": "folder",
359 "code": 59404,
359 "code": 59404,
360 "src": "fontawesome"
360 "src": "fontawesome"
361 },
361 },
362 {
362 {
363 "uid": "c8585e1e5b0467f28b70bce765d5840c",
363 "uid": "c8585e1e5b0467f28b70bce765d5840c",
364 "css": "docs",
364 "css": "docs",
365 "code": 61637,
365 "code": 61637,
366 "src": "fontawesome"
366 "src": "fontawesome"
367 },
367 },
368 {
368 {
369 "uid": "1b5a5d7b7e3c71437f5a26befdd045ed",
369 "uid": "1b5a5d7b7e3c71437f5a26befdd045ed",
370 "css": "doc",
370 "css": "doc",
371 "code": 59414,
371 "code": 59414,
372 "src": "fontawesome"
372 "src": "fontawesome"
373 },
373 },
374 {
374 {
375 "uid": "5408be43f7c42bccee419c6be53fdef5",
375 "uid": "5408be43f7c42bccee419c6be53fdef5",
376 "css": "doc-text",
376 "css": "doc-text",
377 "code": 61686,
377 "code": 61686,
378 "src": "fontawesome"
378 "src": "fontawesome"
379 },
379 },
380 {
380 {
381 "uid": "b091a8bd0fdade174951f17d936f51e4",
381 "uid": "b091a8bd0fdade174951f17d936f51e4",
382 "css": "folder-empty",
382 "css": "folder-empty",
383 "code": 61716,
383 "code": 61716,
384 "src": "fontawesome"
384 "src": "fontawesome"
385 },
385 },
386 {
386 {
387 "uid": "c08a1cde48d96cba21d8c05fa7d7feb1",
387 "uid": "c08a1cde48d96cba21d8c05fa7d7feb1",
388 "css": "doc-text-inv",
388 "css": "doc-text-inv",
389 "code": 61788,
389 "code": 61788,
390 "src": "fontawesome"
390 "src": "fontawesome"
391 },
391 },
392 {
392 {
393 "uid": "178053298e3e5b03551d754d4b9acd8b",
393 "uid": "178053298e3e5b03551d754d4b9acd8b",
394 "css": "doc-inv",
394 "css": "doc-inv",
395 "code": 61787,
395 "code": 61787,
396 "src": "fontawesome"
396 "src": "fontawesome"
397 },
397 },
398 {
398 {
399 "uid": "e99461abfef3923546da8d745372c995",
399 "uid": "e99461abfef3923546da8d745372c995",
400 "css": "cog",
400 "css": "cog",
401 "code": 59415,
401 "code": 59415,
402 "src": "fontawesome"
402 "src": "fontawesome"
403 },
403 },
404 {
404 {
405 "uid": "98687378abd1faf8f6af97c254eb6cd6",
405 "uid": "98687378abd1faf8f6af97c254eb6cd6",
406 "css": "cog-alt",
406 "css": "cog-alt",
407 "code": 59416,
407 "code": 59416,
408 "src": "fontawesome"
408 "src": "fontawesome"
409 },
409 },
410 {
410 {
411 "uid": "21b42d3c3e6be44c3cc3d73042faa216",
411 "uid": "21b42d3c3e6be44c3cc3d73042faa216",
412 "css": "sliders",
412 "css": "sliders",
413 "code": 61918,
413 "code": 61918,
414 "src": "fontawesome"
414 "src": "fontawesome"
415 },
415 },
416 {
416 {
417 "uid": "559647a6f430b3aeadbecd67194451dd",
417 "uid": "559647a6f430b3aeadbecd67194451dd",
418 "css": "menu",
418 "css": "menu",
419 "code": 61641,
419 "code": 61641,
420 "src": "fontawesome"
420 "src": "fontawesome"
421 },
421 },
422 {
422 {
423 "uid": "c5fd349cbd3d23e4ade333789c29c729",
423 "uid": "c5fd349cbd3d23e4ade333789c29c729",
424 "css": "eye",
424 "css": "eye",
425 "code": 59417,
425 "code": 59417,
426 "src": "fontawesome"
426 "src": "fontawesome"
427 },
427 },
428 {
428 {
429 "uid": "7fd683b2c518ceb9e5fa6757f2276faa",
429 "uid": "7fd683b2c518ceb9e5fa6757f2276faa",
430 "css": "eye-off",
430 "css": "eye-off",
431 "code": 59418,
431 "code": 59418,
432 "src": "fontawesome"
432 "src": "fontawesome"
433 },
433 },
434 {
434 {
435 "uid": "2e2dba0307a502a8507c1729084c7ab5",
435 "uid": "2e2dba0307a502a8507c1729084c7ab5",
436 "css": "cancel-circled2",
436 "css": "cancel-circled2",
437 "code": 59419,
437 "code": 59419,
438 "src": "fontawesome"
438 "src": "fontawesome"
439 },
439 },
440 {
440 {
441 "uid": "0f4cae16f34ae243a6144c18a003f2d8",
441 "uid": "0f4cae16f34ae243a6144c18a003f2d8",
442 "css": "cancel-circled",
442 "css": "cancel-circled",
443 "code": 59420,
443 "code": 59420,
444 "src": "fontawesome"
444 "src": "fontawesome"
445 },
445 },
446 {
446 {
447 "uid": "26613a2e6bc41593c54bead46f8c8ee3",
447 "uid": "26613a2e6bc41593c54bead46f8c8ee3",
448 "css": "file-code",
448 "css": "file-code",
449 "code": 61897,
449 "code": 61897,
450 "src": "fontawesome"
450 "src": "fontawesome"
451 },
451 },
452 {
452 {
453 "uid": "5211af474d3a9848f67f945e2ccaf143",
453 "uid": "5211af474d3a9848f67f945e2ccaf143",
454 "css": "remove",
454 "css": "remove",
455 "code": 59408,
455 "code": 59408,
456 "src": "fontawesome"
456 "src": "fontawesome"
457 },
457 },
458 {
458 {
459 "uid": "44e04715aecbca7f266a17d5a7863c68",
459 "uid": "44e04715aecbca7f266a17d5a7863c68",
460 "css": "plus",
460 "css": "plus",
461 "code": 59421,
461 "code": 59421,
462 "src": "fontawesome"
462 "src": "fontawesome"
463 },
463 },
464 {
464 {
465 "uid": "4ba33d2607902cf690dd45df09774cb0",
465 "uid": "4ba33d2607902cf690dd45df09774cb0",
466 "css": "plus-circled",
466 "css": "plus-circled",
467 "code": 59422,
467 "code": 59422,
468 "src": "fontawesome"
468 "src": "fontawesome"
469 },
469 },
470 {
470 {
471 "uid": "1a5cfa186647e8c929c2b17b9fc4dac1",
471 "uid": "1a5cfa186647e8c929c2b17b9fc4dac1",
472 "css": "plus-squared",
472 "css": "plus-squared",
473 "code": 61694,
473 "code": 61694,
474 "src": "fontawesome"
474 "src": "fontawesome"
475 },
475 },
476 {
476 {
477 "uid": "2d3be3e856fc1e4ac067590d2ded1b07",
477 "uid": "2d3be3e856fc1e4ac067590d2ded1b07",
478 "css": "plus-squared-alt",
478 "css": "plus-squared-alt",
479 "code": 61846,
479 "code": 61846,
480 "src": "fontawesome"
480 "src": "fontawesome"
481 },
481 },
482 {
482 {
483 "uid": "eeadb020bb75d089b25d8424aabe19e0",
483 "uid": "eeadb020bb75d089b25d8424aabe19e0",
484 "css": "minus-circled",
484 "css": "minus-circled",
485 "code": 59423,
485 "code": 59423,
486 "src": "fontawesome"
486 "src": "fontawesome"
487 },
487 },
488 {
488 {
489 "uid": "f755a58fb985eeb70bd47d9b31892a34",
489 "uid": "f755a58fb985eeb70bd47d9b31892a34",
490 "css": "minus-squared",
490 "css": "minus-squared",
491 "code": 61766,
491 "code": 61766,
492 "src": "fontawesome"
492 "src": "fontawesome"
493 },
493 },
494 {
494 {
495 "uid": "18ef25350258541e8e54148ed79845c0",
495 "uid": "18ef25350258541e8e54148ed79845c0",
496 "css": "minus-squared-alt",
496 "css": "minus-squared-alt",
497 "code": 61767,
497 "code": 61767,
498 "src": "fontawesome"
498 "src": "fontawesome"
499 },
499 },
500 {
500 {
501 "uid": "861ab06e455e2de3232ebef67d60d708",
501 "uid": "861ab06e455e2de3232ebef67d60d708",
502 "css": "minus",
502 "css": "minus",
503 "code": 59424,
503 "code": 59424,
504 "src": "fontawesome"
504 "src": "fontawesome"
505 },
505 },
506 {
506 {
507 "uid": "e82cedfa1d5f15b00c5a81c9bd731ea2",
507 "uid": "e82cedfa1d5f15b00c5a81c9bd731ea2",
508 "css": "info-circled",
508 "css": "info-circled",
509 "code": 59425,
509 "code": 59425,
510 "src": "fontawesome"
510 "src": "fontawesome"
511 },
511 },
512 {
512 {
513 "uid": "9dd9e835aebe1060ba7190ad2b2ed951",
513 "uid": "9dd9e835aebe1060ba7190ad2b2ed951",
514 "css": "search",
514 "css": "search",
515 "code": 59411,
515 "code": 59411,
516 "src": "fontawesome"
516 "src": "fontawesome"
517 },
517 },
518 {
518 {
519 "uid": "b429436ec5a518c78479d44ef18dbd60",
519 "uid": "b429436ec5a518c78479d44ef18dbd60",
520 "css": "paste",
520 "css": "paste",
521 "code": 61674,
521 "code": 61674,
522 "src": "fontawesome"
522 "src": "fontawesome"
523 },
523 },
524 {
524 {
525 "uid": "8772331a9fec983cdb5d72902a6f9e0e",
525 "uid": "8772331a9fec983cdb5d72902a6f9e0e",
526 "css": "scissors",
526 "css": "scissors",
527 "code": 59412,
527 "code": 59412,
528 "src": "fontawesome"
528 "src": "fontawesome"
529 },
529 },
530 {
530 {
531 "uid": "9a76bc135eac17d2c8b8ad4a5774fc87",
531 "uid": "9a76bc135eac17d2c8b8ad4a5774fc87",
532 "css": "download",
532 "css": "download",
533 "code": 59413,
533 "code": 59413,
534 "src": "fontawesome"
534 "src": "fontawesome"
535 },
535 },
536 {
536 {
537 "uid": "eeec3208c90b7b48e804919d0d2d4a41",
537 "uid": "eeec3208c90b7b48e804919d0d2d4a41",
538 "css": "upload",
538 "css": "upload",
539 "code": 59426,
539 "code": 59426,
540 "src": "fontawesome"
540 "src": "fontawesome"
541 },
541 },
542 {
542 {
543 "uid": "5d2d07f112b8de19f2c0dbfec3e42c05",
543 "uid": "5d2d07f112b8de19f2c0dbfec3e42c05",
544 "css": "spin",
544 "css": "spin",
545 "code": 59448,
545 "code": 59448,
546 "src": "fontelico"
546 "src": "fontelico"
547 },
547 },
548 {
548 {
549 "uid": "9bd60140934a1eb9236fd7a8ab1ff6ba",
549 "uid": "9bd60140934a1eb9236fd7a8ab1ff6ba",
550 "css": "spin-alt",
550 "css": "spin-alt",
551 "code": 59444,
551 "code": 59444,
552 "src": "fontelico"
552 "src": "fontelico"
553 },
553 },
554 {
554 {
555 "uid": "513ac180ff85bd275f2b736720cbbf5e",
556 "css": "home",
557 "code": 59427,
558 "src": "entypo"
559 },
560 {
555 "uid": "c43db6645e7515889fc2193294f50767",
561 "uid": "c43db6645e7515889fc2193294f50767",
556 "css": "plus",
562 "css": "plus",
557 "code": 59411,
563 "code": 59411,
558 "src": "custom_icons",
564 "src": "custom_icons",
559 "selected": false,
565 "selected": false,
560 "svg": {
566 "svg": {
561 "path": "M873.1 446.2H619.2C603.8 446.2 592.3 434.6 592.3 419.2V165.4C592.3 150 580.8 138.5 565.4 138.5H465.4C450 138.5 438.5 150 438.5 165.4V419.2C438.5 434.6 426.9 446.2 411.5 446.2H157.7C142.3 446.2 130.8 457.7 130.8 473.1V573.1C130.8 588.5 142.3 600 157.7 600H411.5C426.9 600 438.5 611.5 438.5 626.9V880.8C438.5 896.2 450 907.7 465.4 907.7H565.4C580.8 907.7 592.3 896.2 592.3 880.8V626.9C592.3 611.5 603.8 600 619.2 600H873.1C888.5 600 900 588.5 900 573.1V473.1C900 457.7 888.5 446.2 873.1 446.2Z",
567 "path": "M873.1 446.2H619.2C603.8 446.2 592.3 434.6 592.3 419.2V165.4C592.3 150 580.8 138.5 565.4 138.5H465.4C450 138.5 438.5 150 438.5 165.4V419.2C438.5 434.6 426.9 446.2 411.5 446.2H157.7C142.3 446.2 130.8 457.7 130.8 473.1V573.1C130.8 588.5 142.3 600 157.7 600H411.5C426.9 600 438.5 611.5 438.5 626.9V880.8C438.5 896.2 450 907.7 465.4 907.7H565.4C580.8 907.7 592.3 896.2 592.3 880.8V626.9C592.3 611.5 603.8 600 619.2 600H873.1C888.5 600 900 588.5 900 573.1V473.1C900 457.7 888.5 446.2 873.1 446.2Z",
562 "width": 1000
568 "width": 1000
563 },
569 },
564 "search": [
570 "search": [
565 "plus"
571 "plus"
566 ]
572 ]
567 },
573 },
568 {
574 {
569 "uid": "7d7f338d90203f20c0d8d5c26091cc69",
575 "uid": "7d7f338d90203f20c0d8d5c26091cc69",
570 "css": "minus",
576 "css": "minus",
571 "code": 59412,
577 "code": 59412,
572 "src": "custom_icons",
578 "src": "custom_icons",
573 "selected": false,
579 "selected": false,
574 "svg": {
580 "svg": {
575 "path": "M980 560H20C10 560 0 550 0 540V380C0 370 10 360 20 360H985C995 360 1005 370 1005 380V545C1000 550 990 560 980 560Z",
581 "path": "M980 560H20C10 560 0 550 0 540V380C0 370 10 360 20 360H985C995 360 1005 370 1005 380V545C1000 550 990 560 980 560Z",
576 "width": 1000
582 "width": 1000
577 },
583 },
578 "search": [
584 "search": [
579 "minus"
585 "minus"
580 ]
586 ]
581 },
587 },
582 {
588 {
583 "uid": "4ccc61480001600f2e7e3c7dd0546c6e",
589 "uid": "4ccc61480001600f2e7e3c7dd0546c6e",
584 "css": "remove",
590 "css": "remove",
585 "code": 59413,
591 "code": 59413,
586 "src": "custom_icons",
592 "src": "custom_icons",
587 "selected": false,
593 "selected": false,
588 "svg": {
594 "svg": {
589 "path": "M975 140L860 25C845 10 825 10 810 25L525 310C510 325 490 325 475 310L190 25C175 10 155 10 140 25L25 140C10 155 10 175 25 190L310 475C325 490 325 510 310 525L25 810C10 825 10 845 25 860L140 975C155 990 175 990 190 975L475 690C490 675 510 675 525 690L810 975C825 990 845 990 860 975L975 860C990 845 990 825 975 810L690 525C675 510 675 490 690 475L975 190C990 180 990 155 975 140Z",
595 "path": "M975 140L860 25C845 10 825 10 810 25L525 310C510 325 490 325 475 310L190 25C175 10 155 10 140 25L25 140C10 155 10 175 25 190L310 475C325 490 325 510 310 525L25 810C10 825 10 845 25 860L140 975C155 990 175 990 190 975L475 690C490 675 510 675 525 690L810 975C825 990 845 990 860 975L975 860C990 845 990 825 975 810L690 525C675 510 675 490 690 475L975 190C990 180 990 155 975 140Z",
590 "width": 1000
596 "width": 1000
591 },
597 },
592 "search": [
598 "search": [
593 "remove"
599 "remove"
594 ]
600 ]
595 }
601 }
596 ]
602 ]
597 } No newline at end of file
603 }
1 NO CONTENT: modified file, binary diff hidden
NO CONTENT: modified file, binary diff hidden
@@ -1,130 +1,132 b''
1 <?xml version="1.0" standalone="no"?>
1 <?xml version="1.0" standalone="no"?>
2 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
2 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3 <svg xmlns="http://www.w3.org/2000/svg">
3 <svg xmlns="http://www.w3.org/2000/svg">
4 <metadata>Copyright (C) 2019 by original authors @ fontello.com</metadata>
4 <metadata>Copyright (C) 2019 by original authors @ fontello.com</metadata>
5 <defs>
5 <defs>
6 <font id="rcicons" horiz-adv-x="1000" >
6 <font id="rcicons" horiz-adv-x="1000" >
7 <font-face font-family="rcicons" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
7 <font-face font-family="rcicons" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
8 <missing-glyph horiz-adv-x="1000" />
8 <missing-glyph horiz-adv-x="1000" />
9 <glyph glyph-name="delete" unicode="&#xe800;" d="M515 758c-211 0-384-173-384-385 0-211 173-385 384-385s385 174 385 385c0 212-173 385-385 385z m227-416c0-15-11-27-30-27h-397c-15 0-30 12-30 27v62c0 15 11 27 30 27h397c15 0 30-12 30-27v-62z" horiz-adv-x="1000" />
9 <glyph glyph-name="delete" unicode="&#xe800;" d="M515 758c-211 0-384-173-384-385 0-211 173-385 384-385s385 174 385 385c0 212-173 385-385 385z m227-416c0-15-11-27-30-27h-397c-15 0-30 12-30 27v62c0 15 11 27 30 27h397c15 0 30-12 30-27v-62z" horiz-adv-x="1000" />
10
10
11 <glyph glyph-name="ok" unicode="&#xe801;" d="M515 735c-211 0-384-173-384-385 0-211 173-385 384-385s385 174 385 385c0 212-173 385-385 385z m239-296l-304-304c-11-12-27-12-38 0l-139 138c-11 12-11 27 0 39l42 42c12 11 27 11 39 0l58-58c11-11 27-11 38 0l219 219c12 12 27 12 39 0l42-42c15-8 15-23 4-34z" horiz-adv-x="1000" />
11 <glyph glyph-name="ok" unicode="&#xe801;" d="M515 735c-211 0-384-173-384-385 0-211 173-385 384-385s385 174 385 385c0 212-173 385-385 385z m239-296l-304-304c-11-12-27-12-38 0l-139 138c-11 12-11 27 0 39l42 42c12 11 27 11 39 0l58-58c11-11 27-11 38 0l219 219c12 12 27 12 39 0l42-42c15-8 15-23 4-34z" horiz-adv-x="1000" />
12
12
13 <glyph glyph-name="comment" unicode="&#xe802;" d="M131 65v504c0 73 58 131 131 131h507c73 0 131-58 131-131v-288c0-73-58-131-131-131h-496c-4 0-11-4-15-8l-93-92c-11-15-34-4-34 15z m131 574c-39 0-73-31-73-74v-411l46 46c4 4 7 8 15 8h519c39 0 73 31 73 73v288c0 39-30 73-73 73h-507z" horiz-adv-x="1000" />
13 <glyph glyph-name="comment" unicode="&#xe802;" d="M131 65v504c0 73 58 131 131 131h507c73 0 131-58 131-131v-288c0-73-58-131-131-131h-496c-4 0-11-4-15-8l-93-92c-11-15-34-4-34 15z m131 574c-39 0-73-31-73-74v-411l46 46c4 4 7 8 15 8h519c39 0 73 31 73 73v288c0 39-30 73-73 73h-507z" horiz-adv-x="1000" />
14
14
15 <glyph glyph-name="bookmark" unicode="&#xe803;" d="M780-140l-260 290c-10 10-25 10-35 0l-260-295c-20-20-45-5-45 30v930c-5 20 10 35 25 35h590c15 0 30-15 30-35v-925c0-35-30-50-45-30z" horiz-adv-x="1000" />
15 <glyph glyph-name="bookmark" unicode="&#xe803;" d="M780-140l-260 290c-10 10-25 10-35 0l-260-295c-20-20-45-5-45 30v930c-5 20 10 35 25 35h590c15 0 30-15 30-35v-925c0-35-30-50-45-30z" horiz-adv-x="1000" />
16
16
17 <glyph glyph-name="branch" unicode="&#xe804;" d="M875 600c0 76-58 134-134 134s-134-58-134-134c0-49 27-89 63-112-18-142-139-183-210-196v313c45 22 71 62 71 111 0 76-58 134-134 134s-134-58-134-134c0-49 27-94 67-116v-500c-40-22-67-67-67-116 0-76 58-134 134-134s134 58 134 134c0 49-26 94-67 116v58c63 9 166 31 246 112 58 58 89 129 98 214 40 22 67 67 67 116z m-478 161c27 0 45-18 45-45s-18-45-45-45-44 18-44 45 18 45 44 45z m0-822c-26 0-44 18-44 45s18 45 44 45 45-18 45-45-22-45-45-45z m344 706c27 0 45-18 45-45s-18-45-45-45-45 18-45 45 23 45 45 45z" horiz-adv-x="1000" />
17 <glyph glyph-name="branch" unicode="&#xe804;" d="M875 600c0 76-58 134-134 134s-134-58-134-134c0-49 27-89 63-112-18-142-139-183-210-196v313c45 22 71 62 71 111 0 76-58 134-134 134s-134-58-134-134c0-49 27-94 67-116v-500c-40-22-67-67-67-116 0-76 58-134 134-134s134 58 134 134c0 49-26 94-67 116v58c63 9 166 31 246 112 58 58 89 129 98 214 40 22 67 67 67 116z m-478 161c27 0 45-18 45-45s-18-45-45-45-44 18-44 45 18 45 44 45z m0-822c-26 0-44 18-44 45s18 45 44 45 45-18 45-45-22-45-45-45z m344 706c27 0 45-18 45-45s-18-45-45-45-45 18-45 45 23 45 45 45z" horiz-adv-x="1000" />
18
18
19 <glyph glyph-name="tag" unicode="&#xe805;" d="M460 788l-366 8c-18 0-31-13-31-31l13-366c0-9 4-13 9-22l464-465c14-13 31-13 45 0l352 353c14 14 14 31 0 45l-468 469c-5 4-14 9-18 9z m-103-224c0-35-31-67-67-67-35 0-67 32-67 67 0 36 32 67 67 67s67-26 67-67z" horiz-adv-x="1000" />
19 <glyph glyph-name="tag" unicode="&#xe805;" d="M460 788l-366 8c-18 0-31-13-31-31l13-366c0-9 4-13 9-22l464-465c14-13 31-13 45 0l352 353c14 14 14 31 0 45l-468 469c-5 4-14 9-18 9z m-103-224c0-35-31-67-67-67-35 0-67 32-67 67 0 36 32 67 67 67s67-26 67-67z" horiz-adv-x="1000" />
20
20
21 <glyph glyph-name="lock" unicode="&#xe806;" d="M813 426h-54v107c0 9 0 13 0 18 0 4 0 9 0 13 0 5 0 5 0 9 0 9 0 14-4 23 0 4 0 4-5 9 0 8-4 13-9 22 0 0 0 4-4 4-5 9-9 18-14 27 0 0-4 5-4 5 4 8 0 17-5 22 0 4-4 4-4 9-5 4-9 13-14 18 0 0-4 4-4 4-9 9-13 14-22 22 0 0-5 0-5 5-4 4-13 9-22 13-5 0-5 5-9 5-4 4-13 9-18 9-4 0-4 4-9 4-9 5-18 9-27 9 0 0 0 0 0 0-9 5-17 5-31 9-4 0-4 0-9 0-4 0-4 0-9 0 0 0-4 0-4 0 0 0-5 0-5 0 0 0 0 0 0 0 0 0 0 0 0 0-4 0-9 0-9 0 0 0-4 0-4 0-4 0-4 0-9 0 0 0 0 0 0 0-4 0-9 0-9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0-4 0-4 0 0 0-5 0-5 0-4 0-4 0-9 0-4 0-4 0-9 0-9 0-22-4-31-9 0 0 0 0 0 0-22 0-36-4-45-9-4 0-4-4-8-4-5-5-9-5-18-9 0-5-5-5-5-5-9-4-18-9-22-18 0 0-5 0-5-4-9-4-13-9-22-18 0 0-4-4-4-4-5-5-9-14-14-18 0-5-4-5-4-9-9-5-14-14-14-18-4 0-4-4-4-4-5-9-9-18-13-27 0 0 0-5-5-5 0-13-4-18-4-26 0-5 0-5-5-9 0-9-4-14-4-23 0-4 0-4 0-9 0-4 0-9 0-13 0-5 0-13 0-18v-107h-49c-18 0-27-13-27-27v-464c0-18 13-27 27-27h620c18 0 27 13 27 27v464c4 18-9 27-22 27z m-451 107c0 67 49 121 111 134 0 0 0 0 5 0 9 0 13 0 22 0 0 0 5 0 5 0 0 0 0 0 0 0 8 0 13 0 22 0 0 0 0 0 4 0 63-13 112-67 112-134v-107h-281v107z" horiz-adv-x="1000" />
21 <glyph glyph-name="lock" unicode="&#xe806;" d="M813 426h-54v107c0 9 0 13 0 18 0 4 0 9 0 13 0 5 0 5 0 9 0 9 0 14-4 23 0 4 0 4-5 9 0 8-4 13-9 22 0 0 0 4-4 4-5 9-9 18-14 27 0 0-4 5-4 5 4 8 0 17-5 22 0 4-4 4-4 9-5 4-9 13-14 18 0 0-4 4-4 4-9 9-13 14-22 22 0 0-5 0-5 5-4 4-13 9-22 13-5 0-5 5-9 5-4 4-13 9-18 9-4 0-4 4-9 4-9 5-18 9-27 9 0 0 0 0 0 0-9 5-17 5-31 9-4 0-4 0-9 0-4 0-4 0-9 0 0 0-4 0-4 0 0 0-5 0-5 0 0 0 0 0 0 0 0 0 0 0 0 0-4 0-9 0-9 0 0 0-4 0-4 0-4 0-4 0-9 0 0 0 0 0 0 0-4 0-9 0-9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0-4 0-4 0 0 0-5 0-5 0-4 0-4 0-9 0-4 0-4 0-9 0-9 0-22-4-31-9 0 0 0 0 0 0-22 0-36-4-45-9-4 0-4-4-8-4-5-5-9-5-18-9 0-5-5-5-5-5-9-4-18-9-22-18 0 0-5 0-5-4-9-4-13-9-22-18 0 0-4-4-4-4-5-5-9-14-14-18 0-5-4-5-4-9-9-5-14-14-14-18-4 0-4-4-4-4-5-9-9-18-13-27 0 0 0-5-5-5 0-13-4-18-4-26 0-5 0-5-5-9 0-9-4-14-4-23 0-4 0-4 0-9 0-4 0-9 0-13 0-5 0-13 0-18v-107h-49c-18 0-27-13-27-27v-464c0-18 13-27 27-27h620c18 0 27 13 27 27v464c4 18-9 27-22 27z m-451 107c0 67 49 121 111 134 0 0 0 0 5 0 9 0 13 0 22 0 0 0 5 0 5 0 0 0 0 0 0 0 8 0 13 0 22 0 0 0 0 0 4 0 63-13 112-67 112-134v-107h-281v107z" horiz-adv-x="1000" />
22
22
23 <glyph glyph-name="unlock" unicode="&#xe807;" d="M781 415h-385v93c0 57 43 104 96 115 0 0 0 0 4 0 8 0 12 0 19 0 0 0 4 0 4 0 0 0 0 0 4 0 8 0 16 0 23-4 0 0 0 0 0 0 8 0 12-4 19-7 0 0 4 0 4-4 4-4 12-4 16-8 0 0 0 0 0 0 4-4 11-8 15-11 0 0 4-4 4-4 4-4 8-8 11-12 0 0 0 0 4-4 4-4 8-11 12-19 0 0 0-4 0-4 4-4 4-11 4-15 0 0 0-4 0-4 0 0 0 0 0-4 4-11 11-19 23-19h57c16 0 27 11 24 27 0 0 0 0 0 0 0 0 0 4 0 4 0 7-4 11-4 19 0 4 0 4-4 8 0 15 0 19-4 27 0 0 0 3-4 3-4 8-8 16-11 23 0 0-4 4-4 4-4 8-8 12-12 16 0 4-4 4-4 7-3 4-7 12-11 16 0 0-4 4-4 4-8 7-12 11-19 19 0 0-4 0-4 4-4 4-12 7-19 11-4 0-4 4-8 4-4 4-12 8-15 8-4 0-4 4-8 4-8 3-15 7-23 7 0 0 0 0 0 0-8 4-16 4-27 8-4 0-4 0-8 0-7 0-11 0-19 4-4 0-8 0-8 0-7 0-15 0-23 0 0 0-4 0-4 0-7 0-15-4-27-4-3 0-11-4-15-4 0 0-4 0-4 0-92-27-157-115-157-215v-93h-43c-15 0-23-11-23-23v-400c0-15 12-23 23-23h535c15 0 23 12 23 23v400c4 12-8 23-23 23z" horiz-adv-x="1000" />
23 <glyph glyph-name="unlock" unicode="&#xe807;" d="M781 415h-385v93c0 57 43 104 96 115 0 0 0 0 4 0 8 0 12 0 19 0 0 0 4 0 4 0 0 0 0 0 4 0 8 0 16 0 23-4 0 0 0 0 0 0 8 0 12-4 19-7 0 0 4 0 4-4 4-4 12-4 16-8 0 0 0 0 0 0 4-4 11-8 15-11 0 0 4-4 4-4 4-4 8-8 11-12 0 0 0 0 4-4 4-4 8-11 12-19 0 0 0-4 0-4 4-4 4-11 4-15 0 0 0-4 0-4 0 0 0 0 0-4 4-11 11-19 23-19h57c16 0 27 11 24 27 0 0 0 0 0 0 0 0 0 4 0 4 0 7-4 11-4 19 0 4 0 4-4 8 0 15 0 19-4 27 0 0 0 3-4 3-4 8-8 16-11 23 0 0-4 4-4 4-4 8-8 12-12 16 0 4-4 4-4 7-3 4-7 12-11 16 0 0-4 4-4 4-8 7-12 11-19 19 0 0-4 0-4 4-4 4-12 7-19 11-4 0-4 4-8 4-4 4-12 8-15 8-4 0-4 4-8 4-8 3-15 7-23 7 0 0 0 0 0 0-8 4-16 4-27 8-4 0-4 0-8 0-7 0-11 0-19 4-4 0-8 0-8 0-7 0-15 0-23 0 0 0-4 0-4 0-7 0-15-4-27-4-3 0-11-4-15-4 0 0-4 0-4 0-92-27-157-115-157-215v-93h-43c-15 0-23-11-23-23v-400c0-15 12-23 23-23h535c15 0 23 12 23 23v400c4 12-8 23-23 23z" horiz-adv-x="1000" />
24
24
25 <glyph glyph-name="feed" unicode="&#xe808;" d="M842 739h-653c-35 0-58-27-58-58v-658c0-31 27-58 58-58h657c31 0 58 27 58 58v658c-4 31-31 58-62 58z m-534-666c-39 0-73 31-73 73s30 73 73 73c38 0 73-30 73-73s-35-73-73-73z m246-11c-35 0-58 27-58 57 0 112-88 200-200 200-31 0-65 27-65 58 0 35 23 62 54 62l11 0c177 0 319-143 319-320-3-30-30-57-61-57z m196 0c-35 0-58 27-58 57 0 220-180 400-400 400-30 0-65 27-65 62 0 34 23 61 54 61l11 0c285 0 520-230 520-519 0-34-27-61-62-61z" horiz-adv-x="1000" />
25 <glyph glyph-name="feed" unicode="&#xe808;" d="M842 739h-653c-35 0-58-27-58-58v-658c0-31 27-58 58-58h657c31 0 58 27 58 58v658c-4 31-31 58-62 58z m-534-666c-39 0-73 31-73 73s30 73 73 73c38 0 73-30 73-73s-35-73-73-73z m246-11c-35 0-58 27-58 57 0 112-88 200-200 200-31 0-65 27-65 58 0 35 23 62 54 62l11 0c177 0 319-143 319-320-3-30-30-57-61-57z m196 0c-35 0-58 27-58 57 0 220-180 400-400 400-30 0-65 27-65 62 0 34 23 61 54 61l11 0c285 0 520-230 520-519 0-34-27-61-62-61z" horiz-adv-x="1000" />
26
26
27 <glyph glyph-name="left" unicode="&#xe809;" d="M692 773l70-69c11-12 11-27 0-39l-289-288c-11-12-11-27 0-38l296-297c12-11 12-27 0-38l-69-69c-11-12-27-12-38 0l-404 404c-12 11-12 26 0 38l396 396c11 12 27 12 38 0z" horiz-adv-x="1000" />
27 <glyph glyph-name="left" unicode="&#xe809;" d="M692 773l70-69c11-12 11-27 0-39l-289-288c-11-12-11-27 0-38l296-297c12-11 12-27 0-38l-69-69c-11-12-27-12-38 0l-404 404c-12 11-12 26 0 38l396 396c11 12 27 12 38 0z" horiz-adv-x="1000" />
28
28
29 <glyph glyph-name="right" unicode="&#xe80a;" d="M339-65l-74 69c-11 11-11 27 0 38l289 289c11 11 11 27 0 38l-296 296c-12 12-12 27 0 39l69 69c12 12 27 12 38 0l404-404c12-11 12-27 0-38l-392-396c-12-12-31-12-38 0z" horiz-adv-x="1000" />
29 <glyph glyph-name="right" unicode="&#xe80a;" d="M339-65l-74 69c-11 11-11 27 0 38l289 289c11 11 11 27 0 38l-296 296c-12 12-12 27 0 39l69 69c12 12 27 12 38 0l404-404c12-11 12-27 0-38l-392-396c-12-12-31-12-38 0z" horiz-adv-x="1000" />
30
30
31 <glyph glyph-name="down" unicode="&#xe80b;" d="M704 454l-173-219c-8-8-23-8-27 0l-173 219c-8 11 0 31 15 31h346c12 0 20-20 12-31z" horiz-adv-x="1000" />
31 <glyph glyph-name="down" unicode="&#xe80b;" d="M704 454l-173-219c-8-8-23-8-27 0l-173 219c-8 11 0 31 15 31h346c12 0 20-20 12-31z" horiz-adv-x="1000" />
32
32
33 <glyph glyph-name="folder" unicode="&#xe80c;" d="M929 511v-393q0-51-37-88t-88-37h-679q-51 0-88 37t-37 88v536q0 51 37 88t88 37h179q51 0 88-37t37-88v-18h375q51 0 88-37t37-88z" horiz-adv-x="928.6" />
33 <glyph glyph-name="folder" unicode="&#xe80c;" d="M929 511v-393q0-51-37-88t-88-37h-679q-51 0-88 37t-37 88v536q0 51 37 88t88 37h179q51 0 88-37t37-88v-18h375q51 0 88-37t37-88z" horiz-adv-x="928.6" />
34
34
35 <glyph glyph-name="folder-open" unicode="&#xe80d;" d="M1049 319q0-17-18-37l-187-221q-24-28-67-48t-81-20h-607q-19 0-33 7t-15 24q0 17 17 37l188 221q24 28 67 48t80 20h607q19 0 34-7t15-24z m-192 192v-90h-464q-53 0-110-26t-92-67l-188-221-2-3q0 2-1 7t0 7v536q0 51 37 88t88 37h179q51 0 88-37t37-88v-18h303q52 0 88-37t37-88z" horiz-adv-x="1071.4" />
35 <glyph glyph-name="folder-open" unicode="&#xe80d;" d="M1049 319q0-17-18-37l-187-221q-24-28-67-48t-81-20h-607q-19 0-33 7t-15 24q0 17 17 37l188 221q24 28 67 48t80 20h607q19 0 34-7t15-24z m-192 192v-90h-464q-53 0-110-26t-92-67l-188-221-2-3q0 2-1 7t0 7v536q0 51 37 88t88 37h179q51 0 88-37t37-88v-18h303q52 0 88-37t37-88z" horiz-adv-x="1071.4" />
36
36
37 <glyph glyph-name="trash-empty" unicode="&#xe80e;" d="M286 439v-321q0-8-5-13t-13-5h-36q-8 0-13 5t-5 13v321q0 8 5 13t13 5h36q8 0 13-5t5-13z m143 0v-321q0-8-5-13t-13-5h-36q-8 0-13 5t-5 13v321q0 8 5 13t13 5h36q8 0 13-5t5-13z m142 0v-321q0-8-5-13t-12-5h-36q-8 0-13 5t-5 13v321q0 8 5 13t13 5h36q7 0 12-5t5-13z m72-404v529h-500v-529q0-12 4-22t8-15 6-5h464q2 0 6 5t8 15 4 22z m-375 601h250l-27 65q-4 5-9 6h-177q-6-1-10-6z m518-18v-36q0-8-5-13t-13-5h-54v-529q0-46-26-80t-63-34h-464q-37 0-63 33t-27 79v531h-53q-8 0-13 5t-5 13v36q0 8 5 13t13 5h172l39 93q9 21 31 35t44 15h178q23 0 44-15t30-35l39-93h173q8 0 13-5t5-13z" horiz-adv-x="785.7" />
37 <glyph glyph-name="trash-empty" unicode="&#xe80e;" d="M286 439v-321q0-8-5-13t-13-5h-36q-8 0-13 5t-5 13v321q0 8 5 13t13 5h36q8 0 13-5t5-13z m143 0v-321q0-8-5-13t-13-5h-36q-8 0-13 5t-5 13v321q0 8 5 13t13 5h36q8 0 13-5t5-13z m142 0v-321q0-8-5-13t-12-5h-36q-8 0-13 5t-5 13v321q0 8 5 13t13 5h36q7 0 12-5t5-13z m72-404v529h-500v-529q0-12 4-22t8-15 6-5h464q2 0 6 5t8 15 4 22z m-375 601h250l-27 65q-4 5-9 6h-177q-6-1-10-6z m518-18v-36q0-8-5-13t-13-5h-54v-529q0-46-26-80t-63-34h-464q-37 0-63 33t-27 79v531h-53q-8 0-13 5t-5 13v36q0 8 5 13t13 5h172l39 93q9 21 31 35t44 15h178q23 0 44-15t30-35l39-93h173q8 0 13-5t5-13z" horiz-adv-x="785.7" />
38
38
39 <glyph glyph-name="group" unicode="&#xe80f;" d="M962 219v-15c0-4-4-12-12-12h-161-4c-16 20-39 39-77 43-35 7-54 15-69 23 7 7 19 11 30 15 46 8 58 23 66 35 7 11 7 23 0 38-8 16-31 43-31 81 0 38 0 104 73 104h8 7c73-4 77-66 73-104 0-38-23-69-30-81-8-15-8-27 0-38 7-12 23-27 65-35 54-4 62-46 62-54 0 0 0 0 0 0z m-708-15c15 15 38 31 69 35 39 7 62 15 73 26-7 8-19 16-34 20-47 7-58 23-66 34-7 12-7 23 0 39 8 15 31 42 31 81 0 38 0 103-73 103h-8-11c-73-3-77-65-73-103 0-39 23-70 30-81 8-16 8-27 0-39-7-11-23-27-65-34-46-8-54-50-54-54 0 0 0 0 0 0v-16c0-3 4-11 12-11h161 8z m454 11c-73 12-96 35-108 54-11 20-11 39 0 62 12 23 50 69 54 131 4 61 0 165-119 169h-16-15c-119-4-123-104-119-166 4-61 38-107 54-130 11-23 11-43 0-62-12-19-35-42-108-54-73-11-85-80-85-88 0 0 0 0 0 0v-23c0-8 8-16 16-16h257 258c8 0 15 8 15 16v23c0 0 0 0 0 0-3 4-11 73-84 84z" horiz-adv-x="1000" />
39 <glyph glyph-name="group" unicode="&#xe80f;" d="M962 219v-15c0-4-4-12-12-12h-161-4c-16 20-39 39-77 43-35 7-54 15-69 23 7 7 19 11 30 15 46 8 58 23 66 35 7 11 7 23 0 38-8 16-31 43-31 81 0 38 0 104 73 104h8 7c73-4 77-66 73-104 0-38-23-69-30-81-8-15-8-27 0-38 7-12 23-27 65-35 54-4 62-46 62-54 0 0 0 0 0 0z m-708-15c15 15 38 31 69 35 39 7 62 15 73 26-7 8-19 16-34 20-47 7-58 23-66 34-7 12-7 23 0 39 8 15 31 42 31 81 0 38 0 103-73 103h-8-11c-73-3-77-65-73-103 0-39 23-70 30-81 8-16 8-27 0-39-7-11-23-27-65-34-46-8-54-50-54-54 0 0 0 0 0 0v-16c0-3 4-11 12-11h161 8z m454 11c-73 12-96 35-108 54-11 20-11 39 0 62 12 23 50 69 54 131 4 61 0 165-119 169h-16-15c-119-4-123-104-119-166 4-61 38-107 54-130 11-23 11-43 0-62-12-19-35-42-108-54-73-11-85-80-85-88 0 0 0 0 0 0v-23c0-8 8-16 16-16h257 258c8 0 15 8 15 16v23c0 0 0 0 0 0-3 4-11 73-84 84z" horiz-adv-x="1000" />
40
40
41 <glyph glyph-name="remove" unicode="&#xe810;" d="M724 112q0-22-15-38l-76-76q-16-15-38-15t-38 15l-164 165-164-165q-16-15-38-15t-38 15l-76 76q-16 16-16 38t16 38l164 164-164 164q-16 16-16 38t16 38l76 76q16 16 38 16t38-16l164-164 164 164q16 16 38 16t38-16l76-76q15-15 15-38t-15-38l-164-164 164-164q15-15 15-38z" horiz-adv-x="785.7" />
41 <glyph glyph-name="remove" unicode="&#xe810;" d="M724 112q0-22-15-38l-76-76q-16-15-38-15t-38 15l-164 165-164-165q-16-15-38-15t-38 15l-76 76q-16 16-16 38t16 38l164 164-164 164q-16 16-16 38t16 38l76 76q16 16 38 16t38-16l164-164 164 164q16 16 38 16t38-16l76-76q15-15 15-38t-15-38l-164-164 164-164q15-15 15-38z" horiz-adv-x="785.7" />
42
42
43 <glyph glyph-name="fork" unicode="&#xe811;" d="M792 654c0 58-46 100-100 100-57 0-100-46-100-100 0-35 20-65 47-85-12-84-70-123-127-142-58 15-116 54-127 142 27 20 46 50 46 85 0 58-46 100-100 100s-108-42-108-100c0-39 23-73 54-89 12-107 77-188 181-226v-162c-31-19-50-50-50-88 0-58 46-101 100-101s100 47 100 101c0 38-19 69-50 88v162c104 38 169 119 181 226 30 20 53 50 53 89z m-465 35c19 0 35-16 35-35s-16-31-35-31-35 12-35 31 16 35 35 35z m181-635c-19 0-35 15-35 35s16 34 35 34c19 0 34-15 34-34s-15-35-34-35z m184 635c20 0 35-16 35-35s-15-31-35-31-34 16-34 35 15 31 34 31z" horiz-adv-x="1000" />
43 <glyph glyph-name="fork" unicode="&#xe811;" d="M792 654c0 58-46 100-100 100-57 0-100-46-100-100 0-35 20-65 47-85-12-84-70-123-127-142-58 15-116 54-127 142 27 20 46 50 46 85 0 58-46 100-100 100s-108-42-108-100c0-39 23-73 54-89 12-107 77-188 181-226v-162c-31-19-50-50-50-88 0-58 46-101 100-101s100 47 100 101c0 38-19 69-50 88v162c104 38 169 119 181 226 30 20 53 50 53 89z m-465 35c19 0 35-16 35-35s-16-31-35-31-35 12-35 31 16 35 35 35z m181-635c-19 0-35 15-35 35s16 34 35 34c19 0 34-15 34-34s-15-35-34-35z m184 635c20 0 35-16 35-35s-15-31-35-31-34 16-34 35 15 31 34 31z" horiz-adv-x="1000" />
44
44
45 <glyph glyph-name="more" unicode="&#xe812;" d="M546 435h-100c-15 0-27-12-27-27v-100c0-16 12-27 27-27h100c16 0 27 11 27 27v100c0 15-11 27-27 27z m0 307h-100c-15 0-27-11-27-27v-100c0-15 12-26 27-26h100c16 0 27 11 27 26v100c0 16-11 27-27 27z m0-615h-100c-15 0-27-12-27-27v-100c0-15 12-27 27-27h100c16 0 27 12 27 27v100c0 15-11 27-27 27z" horiz-adv-x="1000" />
45 <glyph glyph-name="more" unicode="&#xe812;" d="M546 435h-100c-15 0-27-12-27-27v-100c0-16 12-27 27-27h100c16 0 27 11 27 27v100c0 15-11 27-27 27z m0 307h-100c-15 0-27-11-27-27v-100c0-15 12-26 27-26h100c16 0 27 11 27 26v100c0 16-11 27-27 27z m0-615h-100c-15 0-27-12-27-27v-100c0-15 12-27 27-27h100c16 0 27 12 27 27v100c0 15-11 27-27 27z" horiz-adv-x="1000" />
46
46
47 <glyph glyph-name="search" unicode="&#xe813;" d="M643 386q0 103-73 176t-177 74-177-74-73-176 73-177 177-73 177 73 73 177z m286-465q0-29-22-50t-50-21q-30 0-50 21l-191 191q-100-69-223-69-80 0-153 31t-125 84-84 125-31 153 31 152 84 126 125 84 153 31 153-31 125-84 84-126 31-152q0-123-69-223l191-191q21-21 21-51z" horiz-adv-x="928.6" />
47 <glyph glyph-name="search" unicode="&#xe813;" d="M643 386q0 103-73 176t-177 74-177-74-73-176 73-177 177-73 177 73 73 177z m286-465q0-29-22-50t-50-21q-30 0-50 21l-191 191q-100-69-223-69-80 0-153 31t-125 84-84 125-31 153 31 152 84 126 125 84 153 31 153-31 125-84 84-126 31-152q0-123-69-223l191-191q21-21 21-51z" horiz-adv-x="928.6" />
48
48
49 <glyph glyph-name="scissors" unicode="&#xe814;" d="M536 350q14 0 25-11t10-25-10-25-25-10-25 10-11 25 11 25 25 11z m167-36l283-222q16-11 14-31-3-20-19-28l-72-36q-7-4-16-4-10 0-17 4l-385 216-62-36q-4-3-7-3 8-28 6-54-4-43-31-83t-74-69q-74-47-154-47-76 0-124 44-51 47-44 116 4 42 31 82t73 69q74 47 155 47 46 0 84-18 5 8 13 13l68 40-68 41q-8 5-13 12-38-17-84-17-81 0-155 47-46 30-73 69t-31 82q-3 33 8 63t36 52q47 44 124 44 80 0 154-47 46-29 74-68t31-83q2-27-6-54 3-1 7-3l62-37 385 216q7 5 17 5 9 0 16-4l72-36q16-9 19-28 2-20-14-32z m-380 145q26 24 12 61t-59 65q-52 33-107 33-42 0-63-20-26-24-12-60t59-66q51-33 107-33 41 0 63 20z m-47-415q45 28 59 65t-12 60q-22 20-63 20-56 0-107-33-45-28-59-65t12-60q21-20 63-20 55 0 107 33z m99 342l54-33v7q0 20 18 31l8 4-44 26-15-14q-1-2-5-6t-7-7q-1-1-2-2t-2-1z m125-125l54-18 410 321-71 36-429-240v-64l-89-53 5-5q1-1 4-3 2-2 6-7t6-6l15-15z m393-232l71 35-290 228-99-77q-1-2-7-4z" horiz-adv-x="1000" />
49 <glyph glyph-name="scissors" unicode="&#xe814;" d="M536 350q14 0 25-11t10-25-10-25-25-10-25 10-11 25 11 25 25 11z m167-36l283-222q16-11 14-31-3-20-19-28l-72-36q-7-4-16-4-10 0-17 4l-385 216-62-36q-4-3-7-3 8-28 6-54-4-43-31-83t-74-69q-74-47-154-47-76 0-124 44-51 47-44 116 4 42 31 82t73 69q74 47 155 47 46 0 84-18 5 8 13 13l68 40-68 41q-8 5-13 12-38-17-84-17-81 0-155 47-46 30-73 69t-31 82q-3 33 8 63t36 52q47 44 124 44 80 0 154-47 46-29 74-68t31-83q2-27-6-54 3-1 7-3l62-37 385 216q7 5 17 5 9 0 16-4l72-36q16-9 19-28 2-20-14-32z m-380 145q26 24 12 61t-59 65q-52 33-107 33-42 0-63-20-26-24-12-60t59-66q51-33 107-33 41 0 63 20z m-47-415q45 28 59 65t-12 60q-22 20-63 20-56 0-107-33-45-28-59-65t12-60q21-20 63-20 55 0 107 33z m99 342l54-33v7q0 20 18 31l8 4-44 26-15-14q-1-2-5-6t-7-7q-1-1-2-2t-2-1z m125-125l54-18 410 321-71 36-429-240v-64l-89-53 5-5q1-1 4-3 2-2 6-7t6-6l15-15z m393-232l71 35-290 228-99-77q-1-2-7-4z" horiz-adv-x="1000" />
50
50
51 <glyph glyph-name="download" unicode="&#xe815;" d="M714 100q0 15-10 25t-25 11-25-11-11-25 11-25 25-11 25 11 10 25z m143 0q0 15-10 25t-26 11-25-11-10-25 10-25 25-11 26 11 10 25z m72 125v-179q0-22-16-37t-38-16h-821q-23 0-38 16t-16 37v179q0 22 16 38t38 16h259l75-76q33-32 76-32t76 32l76 76h259q22 0 38-16t16-38z m-182 318q10-23-8-39l-250-250q-10-11-25-11t-25 11l-250 250q-17 16-8 39 10 21 33 21h143v250q0 15 11 25t25 11h143q14 0 25-11t10-25v-250h143q24 0 33-21z" horiz-adv-x="928.6" />
51 <glyph glyph-name="download" unicode="&#xe815;" d="M714 100q0 15-10 25t-25 11-25-11-11-25 11-25 25-11 25 11 10 25z m143 0q0 15-10 25t-26 11-25-11-10-25 10-25 25-11 26 11 10 25z m72 125v-179q0-22-16-37t-38-16h-821q-23 0-38 16t-16 37v179q0 22 16 38t38 16h259l75-76q33-32 76-32t76 32l76 76h259q22 0 38-16t16-38z m-182 318q10-23-8-39l-250-250q-10-11-25-11t-25 11l-250 250q-17 16-8 39 10 21 33 21h143v250q0 15 11 25t25 11h143q14 0 25-11t10-25v-250h143q24 0 33-21z" horiz-adv-x="928.6" />
52
52
53 <glyph glyph-name="doc" unicode="&#xe816;" d="M819 638q16-16 27-42t11-50v-642q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h500q22 0 49-11t42-27z m-248 136v-210h210q-5 17-12 23l-175 175q-6 7-23 12z m215-853v572h-232q-23 0-38 16t-16 37v233h-429v-858h715z" horiz-adv-x="857.1" />
53 <glyph glyph-name="doc" unicode="&#xe816;" d="M819 638q16-16 27-42t11-50v-642q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h500q22 0 49-11t42-27z m-248 136v-210h210q-5 17-12 23l-175 175q-6 7-23 12z m215-853v572h-232q-23 0-38 16t-16 37v233h-429v-858h715z" horiz-adv-x="857.1" />
54
54
55 <glyph glyph-name="cog" unicode="&#xe817;" d="M571 350q0 59-41 101t-101 42-101-42-42-101 42-101 101-42 101 42 41 101z m286 61v-124q0-7-4-13t-11-7l-104-16q-10-30-21-51 19-27 59-77 6-6 6-13t-5-13q-15-21-55-61t-53-39q-7 0-14 5l-77 60q-25-13-51-21-9-76-16-104-4-16-20-16h-124q-8 0-14 5t-6 12l-16 103q-27 9-50 21l-79-60q-6-5-14-5-8 0-14 6-70 64-92 94-4 5-4 13 0 6 5 12 8 12 28 37t30 40q-15 28-23 55l-102 15q-7 1-11 7t-5 13v124q0 7 5 13t10 7l104 16q8 25 22 51-23 32-60 77-6 7-6 14 0 5 5 12 15 20 55 60t53 40q7 0 15-5l77-60q24 13 50 21 9 76 17 104 3 16 20 16h124q7 0 13-5t7-12l15-103q28-9 51-20l79 59q5 5 13 5 7 0 14-5 72-67 92-95 4-5 4-12 0-7-4-13-9-12-29-37t-30-40q15-28 23-54l102-16q7-1 12-7t4-13z" horiz-adv-x="857.1" />
55 <glyph glyph-name="cog" unicode="&#xe817;" d="M571 350q0 59-41 101t-101 42-101-42-42-101 42-101 101-42 101 42 41 101z m286 61v-124q0-7-4-13t-11-7l-104-16q-10-30-21-51 19-27 59-77 6-6 6-13t-5-13q-15-21-55-61t-53-39q-7 0-14 5l-77 60q-25-13-51-21-9-76-16-104-4-16-20-16h-124q-8 0-14 5t-6 12l-16 103q-27 9-50 21l-79-60q-6-5-14-5-8 0-14 6-70 64-92 94-4 5-4 13 0 6 5 12 8 12 28 37t30 40q-15 28-23 55l-102 15q-7 1-11 7t-5 13v124q0 7 5 13t10 7l104 16q8 25 22 51-23 32-60 77-6 7-6 14 0 5 5 12 15 20 55 60t53 40q7 0 15-5l77-60q24 13 50 21 9 76 17 104 3 16 20 16h124q7 0 13-5t7-12l15-103q28-9 51-20l79 59q5 5 13 5 7 0 14-5 72-67 92-95 4-5 4-12 0-7-4-13-9-12-29-37t-30-40q15-28 23-54l102-16q7-1 12-7t4-13z" horiz-adv-x="857.1" />
56
56
57 <glyph glyph-name="cog-alt" unicode="&#xe818;" d="M500 350q0 59-42 101t-101 42-101-42-42-101 42-101 101-42 101 42 42 101z m429-286q0 29-22 51t-50 21-50-21-21-51q0-29 21-50t50-21 51 21 21 50z m0 572q0 29-22 50t-50 21-50-21-21-50q0-30 21-51t50-21 51 21 21 51z m-215-235v-103q0-6-4-11t-8-6l-87-14q-6-19-18-42 19-27 50-64 4-6 4-11 0-7-4-11-12-17-46-50t-43-33q-7 0-12 4l-64 50q-21-11-43-17-6-60-13-87-4-13-17-13h-104q-6 0-11 4t-5 10l-13 85q-19 6-42 18l-66-50q-4-4-11-4-6 0-12 4-80 75-80 90 0 5 4 10 5 8 23 30t26 34q-13 24-20 46l-85 13q-5 1-9 5t-4 11v104q0 5 4 10t9 6l86 14q7 19 18 42-19 27-50 64-4 6-4 11 0 7 4 12 12 16 46 49t44 33q6 0 12-4l64-50q19 10 43 18 6 60 13 86 3 13 16 13h104q6 0 11-4t6-10l13-85q19-6 42-17l65 49q5 4 12 4 6 0 11-4 81-75 81-90 0-4-4-10-7-9-24-30t-25-34q13-27 19-46l85-12q6-2 9-6t4-11z m357-298v-78q0-9-83-17-6-15-16-29 28-63 28-77 0-2-2-4-68-40-69-40-5 0-26 27t-29 37q-11-1-17-1t-17 1q-7-11-29-37t-25-27q-1 0-69 40-3 2-3 4 0 14 29 77-10 14-17 29-83 8-83 17v78q0 9 83 18 7 16 17 29-29 63-29 77 0 2 3 4 2 1 19 11t33 19 17 9q4 0 25-26t29-38q12 1 17 1t17-1q28 40 51 63l4 1q2 0 69-39 2-2 2-4 0-14-28-77 9-13 16-29 83-9 83-18z m0 572v-78q0-9-83-18-6-15-16-29 28-63 28-77 0-2-2-4-68-39-69-39-5 0-26 26t-29 38q-11-1-17-1t-17 1q-7-12-29-38t-25-26q-1 0-69 39-3 2-3 4 0 14 29 77-10 14-17 29-83 9-83 18v78q0 9 83 17 7 16 17 29-29 63-29 77 0 2 3 4 2 1 19 11t33 19 17 9q4 0 25-26t29-37q12 1 17 1t17-1q28 39 51 62l4 1q2 0 69-39 2-2 2-4 0-14-28-77 9-13 16-29 83-8 83-17z" horiz-adv-x="1071.4" />
57 <glyph glyph-name="cog-alt" unicode="&#xe818;" d="M500 350q0 59-42 101t-101 42-101-42-42-101 42-101 101-42 101 42 42 101z m429-286q0 29-22 51t-50 21-50-21-21-51q0-29 21-50t50-21 51 21 21 50z m0 572q0 29-22 50t-50 21-50-21-21-50q0-30 21-51t50-21 51 21 21 51z m-215-235v-103q0-6-4-11t-8-6l-87-14q-6-19-18-42 19-27 50-64 4-6 4-11 0-7-4-11-12-17-46-50t-43-33q-7 0-12 4l-64 50q-21-11-43-17-6-60-13-87-4-13-17-13h-104q-6 0-11 4t-5 10l-13 85q-19 6-42 18l-66-50q-4-4-11-4-6 0-12 4-80 75-80 90 0 5 4 10 5 8 23 30t26 34q-13 24-20 46l-85 13q-5 1-9 5t-4 11v104q0 5 4 10t9 6l86 14q7 19 18 42-19 27-50 64-4 6-4 11 0 7 4 12 12 16 46 49t44 33q6 0 12-4l64-50q19 10 43 18 6 60 13 86 3 13 16 13h104q6 0 11-4t6-10l13-85q19-6 42-17l65 49q5 4 12 4 6 0 11-4 81-75 81-90 0-4-4-10-7-9-24-30t-25-34q13-27 19-46l85-12q6-2 9-6t4-11z m357-298v-78q0-9-83-17-6-15-16-29 28-63 28-77 0-2-2-4-68-40-69-40-5 0-26 27t-29 37q-11-1-17-1t-17 1q-7-11-29-37t-25-27q-1 0-69 40-3 2-3 4 0 14 29 77-10 14-17 29-83 8-83 17v78q0 9 83 18 7 16 17 29-29 63-29 77 0 2 3 4 2 1 19 11t33 19 17 9q4 0 25-26t29-38q12 1 17 1t17-1q28 40 51 63l4 1q2 0 69-39 2-2 2-4 0-14-28-77 9-13 16-29 83-9 83-18z m0 572v-78q0-9-83-18-6-15-16-29 28-63 28-77 0-2-2-4-68-39-69-39-5 0-26 26t-29 38q-11-1-17-1t-17 1q-7-12-29-38t-25-26q-1 0-69 39-3 2-3 4 0 14 29 77-10 14-17 29-83 9-83 18v78q0 9 83 17 7 16 17 29-29 63-29 77 0 2 3 4 2 1 19 11t33 19 17 9q4 0 25-26t29-37q12 1 17 1t17-1q28 39 51 62l4 1q2 0 69-39 2-2 2-4 0-14-28-77 9-13 16-29 83-8 83-17z" horiz-adv-x="1071.4" />
58
58
59 <glyph glyph-name="eye" unicode="&#xe819;" d="M929 314q-85 132-213 197 34-58 34-125 0-103-73-177t-177-73-177 73-73 177q0 67 34 125-128-65-213-197 75-114 187-182t242-68 243 68 186 182z m-402 215q0 11-8 19t-19 7q-70 0-120-50t-50-119q0-11 8-19t19-8 19 8 8 19q0 48 34 82t82 34q11 0 19 8t8 19z m473-215q0-19-11-38-78-129-210-206t-279-77-279 77-210 206q-11 19-11 38t11 39q78 128 210 205t279 78 279-78 210-205q11-20 11-39z" horiz-adv-x="1000" />
59 <glyph glyph-name="eye" unicode="&#xe819;" d="M929 314q-85 132-213 197 34-58 34-125 0-103-73-177t-177-73-177 73-73 177q0 67 34 125-128-65-213-197 75-114 187-182t242-68 243 68 186 182z m-402 215q0 11-8 19t-19 7q-70 0-120-50t-50-119q0-11 8-19t19-8 19 8 8 19q0 48 34 82t82 34q11 0 19 8t8 19z m473-215q0-19-11-38-78-129-210-206t-279-77-279 77-210 206q-11 19-11 38t11 39q78 128 210 205t279 78 279-78 210-205q11-20 11-39z" horiz-adv-x="1000" />
60
60
61 <glyph glyph-name="eye-off" unicode="&#xe81a;" d="M310 105l43 79q-48 35-76 88t-27 114q0 67 34 125-128-65-213-197 94-144 239-209z m217 424q0 11-8 19t-19 7q-70 0-120-50t-50-119q0-11 8-19t19-8 19 8 8 19q0 48 34 82t82 34q11 0 19 8t8 19z m202 106q0-4 0-5-59-105-176-316t-176-316l-28-50q-5-9-15-9-7 0-75 39-9 6-9 16 0 7 25 49-80 36-147 96t-117 137q-11 17-11 38t11 39q86 131 212 207t277 76q50 0 100-10l31 54q5 9 15 9 3 0 10-3t18-9 18-10 18-10 10-7q9-5 9-15z m21-249q0-78-44-142t-117-91l157 280q4-25 4-47z m250-72q0-19-11-38-22-36-61-81-84-96-194-149t-234-53l41 74q119 10 219 76t169 171q-65 100-158 164l35 63q53-36 102-85t81-103q11-19 11-39z" horiz-adv-x="1000" />
61 <glyph glyph-name="eye-off" unicode="&#xe81a;" d="M310 105l43 79q-48 35-76 88t-27 114q0 67 34 125-128-65-213-197 94-144 239-209z m217 424q0 11-8 19t-19 7q-70 0-120-50t-50-119q0-11 8-19t19-8 19 8 8 19q0 48 34 82t82 34q11 0 19 8t8 19z m202 106q0-4 0-5-59-105-176-316t-176-316l-28-50q-5-9-15-9-7 0-75 39-9 6-9 16 0 7 25 49-80 36-147 96t-117 137q-11 17-11 38t11 39q86 131 212 207t277 76q50 0 100-10l31 54q5 9 15 9 3 0 10-3t18-9 18-10 18-10 10-7q9-5 9-15z m21-249q0-78-44-142t-117-91l157 280q4-25 4-47z m250-72q0-19-11-38-22-36-61-81-84-96-194-149t-234-53l41 74q119 10 219 76t169 171q-65 100-158 164l35 63q53-36 102-85t81-103q11-19 11-39z" horiz-adv-x="1000" />
62
62
63 <glyph glyph-name="cancel-circled2" unicode="&#xe81b;" d="M612 248l-81-82q-6-5-13-5t-13 5l-76 77-77-77q-5-5-13-5t-12 5l-82 82q-6 6-6 13t6 13l76 76-76 77q-6 5-6 12t6 13l82 82q5 5 12 5t13-5l77-77 76 77q6 5 13 5t13-5l81-82q6-5 6-13t-6-12l-76-77 76-76q6-6 6-13t-6-13z m120 102q0 83-41 152t-110 111-152 41-153-41-110-111-41-152 41-152 110-111 153-41 152 41 110 111 41 152z m125 0q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
63 <glyph glyph-name="cancel-circled2" unicode="&#xe81b;" d="M612 248l-81-82q-6-5-13-5t-13 5l-76 77-77-77q-5-5-13-5t-12 5l-82 82q-6 6-6 13t6 13l76 76-76 77q-6 5-6 12t6 13l82 82q5 5 12 5t13-5l77-77 76 77q6 5 13 5t13-5l81-82q6-5 6-13t-6-12l-76-77 76-76q6-6 6-13t-6-13z m120 102q0 83-41 152t-110 111-152 41-153-41-110-111-41-152 41-152 110-111 153-41 152 41 110 111 41 152z m125 0q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
64
64
65 <glyph glyph-name="cancel-circled" unicode="&#xe81c;" d="M641 224q0 14-10 25l-101 101 101 101q10 11 10 25 0 15-10 26l-51 50q-10 11-25 11-15 0-25-11l-101-101-101 101q-11 11-25 11-16 0-26-11l-50-50q-11-11-11-26 0-14 11-25l101-101-101-101q-11-11-11-25 0-15 11-26l50-50q10-11 26-11 14 0 25 11l101 101 101-101q10-11 25-11 15 0 25 11l51 50q10 11 10 26z m216 126q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
65 <glyph glyph-name="cancel-circled" unicode="&#xe81c;" d="M641 224q0 14-10 25l-101 101 101 101q10 11 10 25 0 15-10 26l-51 50q-10 11-25 11-15 0-25-11l-101-101-101 101q-11 11-25 11-16 0-26-11l-50-50q-11-11-11-26 0-14 11-25l101-101-101-101q-11-11-11-25 0-15 11-26l50-50q10-11 26-11 14 0 25 11l101 101 101-101q10-11 25-11 15 0 25 11l51 50q10 11 10 26z m216 126q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
66
66
67 <glyph glyph-name="plus" unicode="&#xe81d;" d="M786 439v-107q0-22-16-38t-38-15h-232v-233q0-22-16-37t-38-16h-107q-22 0-38 16t-15 37v233h-232q-23 0-38 15t-16 38v107q0 23 16 38t38 16h232v232q0 22 15 38t38 16h107q23 0 38-16t16-38v-232h232q23 0 38-16t16-38z" horiz-adv-x="785.7" />
67 <glyph glyph-name="plus" unicode="&#xe81d;" d="M786 439v-107q0-22-16-38t-38-15h-232v-233q0-22-16-37t-38-16h-107q-22 0-38 16t-15 37v233h-232q-23 0-38 15t-16 38v107q0 23 16 38t38 16h232v232q0 22 15 38t38 16h107q23 0 38-16t16-38v-232h232q23 0 38-16t16-38z" horiz-adv-x="785.7" />
68
68
69 <glyph glyph-name="plus-circled" unicode="&#xe81e;" d="M679 314v72q0 14-11 25t-25 10h-143v143q0 15-11 25t-25 11h-71q-15 0-25-11t-11-25v-143h-143q-14 0-25-10t-10-25v-72q0-14 10-25t25-10h143v-143q0-15 11-25t25-11h71q15 0 25 11t11 25v143h143q14 0 25 10t11 25z m178 36q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
69 <glyph glyph-name="plus-circled" unicode="&#xe81e;" d="M679 314v72q0 14-11 25t-25 10h-143v143q0 15-11 25t-25 11h-71q-15 0-25-11t-11-25v-143h-143q-14 0-25-10t-10-25v-72q0-14 10-25t25-10h143v-143q0-15 11-25t25-11h71q15 0 25 11t11 25v143h143q14 0 25 10t11 25z m178 36q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
70
70
71 <glyph glyph-name="minus-circled" unicode="&#xe81f;" d="M679 314v72q0 14-11 25t-25 10h-429q-14 0-25-10t-10-25v-72q0-14 10-25t25-10h429q14 0 25 10t11 25z m178 36q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
71 <glyph glyph-name="minus-circled" unicode="&#xe81f;" d="M679 314v72q0 14-11 25t-25 10h-429q-14 0-25-10t-10-25v-72q0-14 10-25t25-10h429q14 0 25 10t11 25z m178 36q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
72
72
73 <glyph glyph-name="minus" unicode="&#xe820;" d="M786 439v-107q0-22-16-38t-38-15h-678q-23 0-38 15t-16 38v107q0 23 16 38t38 16h678q23 0 38-16t16-38z" horiz-adv-x="785.7" />
73 <glyph glyph-name="minus" unicode="&#xe820;" d="M786 439v-107q0-22-16-38t-38-15h-678q-23 0-38 15t-16 38v107q0 23 16 38t38 16h678q23 0 38-16t16-38z" horiz-adv-x="785.7" />
74
74
75 <glyph glyph-name="info-circled" unicode="&#xe821;" d="M571 82v89q0 8-5 13t-12 5h-54v286q0 8-5 13t-13 5h-178q-8 0-13-5t-5-13v-89q0-8 5-13t13-5h53v-179h-53q-8 0-13-5t-5-13v-89q0-8 5-13t13-5h250q7 0 12 5t5 13z m-71 500v89q0 8-5 13t-13 5h-107q-8 0-13-5t-5-13v-89q0-8 5-13t13-5h107q8 0 13 5t5 13z m357-232q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
75 <glyph glyph-name="info-circled" unicode="&#xe821;" d="M571 82v89q0 8-5 13t-12 5h-54v286q0 8-5 13t-13 5h-178q-8 0-13-5t-5-13v-89q0-8 5-13t13-5h53v-179h-53q-8 0-13-5t-5-13v-89q0-8 5-13t13-5h250q7 0 12 5t5 13z m-71 500v89q0 8-5 13t-13 5h-107q-8 0-13-5t-5-13v-89q0-8 5-13t13-5h107q8 0 13 5t5 13z m357-232q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
76
76
77 <glyph glyph-name="upload" unicode="&#xe822;" d="M714 29q0 14-10 25t-25 10-25-10-11-25 11-25 25-11 25 11 10 25z m143 0q0 14-10 25t-26 10-25-10-10-25 10-25 25-11 26 11 10 25z m72 125v-179q0-22-16-38t-38-16h-821q-23 0-38 16t-16 38v179q0 22 16 38t38 15h238q12-31 39-51t62-20h143q34 0 61 20t40 51h238q22 0 38-15t16-38z m-182 361q-9-22-33-22h-143v-250q0-15-10-25t-25-11h-143q-15 0-25 11t-11 25v250h-143q-23 0-33 22-9 22 8 39l250 250q10 10 25 10t25-10l250-250q18-17 8-39z" horiz-adv-x="928.6" />
77 <glyph glyph-name="upload" unicode="&#xe822;" d="M714 29q0 14-10 25t-25 10-25-10-11-25 11-25 25-11 25 11 10 25z m143 0q0 14-10 25t-26 10-25-10-10-25 10-25 25-11 26 11 10 25z m72 125v-179q0-22-16-38t-38-16h-821q-23 0-38 16t-16 38v179q0 22 16 38t38 15h238q12-31 39-51t62-20h143q34 0 61 20t40 51h238q22 0 38-15t16-38z m-182 361q-9-22-33-22h-143v-250q0-15-10-25t-25-11h-143q-15 0-25 11t-11 25v250h-143q-23 0-33 22-9 22 8 39l250 250q10 10 25 10t25-10l250-250q18-17 8-39z" horiz-adv-x="928.6" />
78
78
79 <glyph glyph-name="home" unicode="&#xe823;" d="M888 336q16-16 11-27t-27-11l-84 0 0-310q0-14-1-21t-8-13-23-6l-204 0 0 310-204 0 0-310-194 0q-28 0-35 10t-7 30l0 310-84 0q-22 0-27 11t11 27l400 402q16 16 38 16t38-16z" horiz-adv-x="900" />
80
79 <glyph glyph-name="git" unicode="&#xe82a;" d="M929 844h-858c-36 0-65-30-65-65v-857c0-36 30-65 65-65h857c36 0 65 30 65 65v857c1 35-29 65-64 65z m-729-549c4-11 9-20 14-27 6-8 14-14 22-18 9-4 19-6 29-6 9 0 16 1 24 2 7 2 14 4 20 7l6 51h-27c-4 0-8 1-10 4-2 1-3 5-3 7l5 39h105l-16-131c-8-7-16-12-25-15-9-4-18-8-28-10-10-3-18-5-30-7-10-1-21-2-33-2-20 0-38 4-54 11-16 8-30 18-41 30-12 13-20 28-27 45-6 18-10 36-10 56 0 18 3 34 7 50 3 17 10 30 17 44 8 14 16 25 26 36 10 12 22 20 34 28 13 7 26 14 41 17 15 4 30 7 47 7 13 0 25-2 36-4 11-3 21-6 29-10 8-4 16-9 22-14 6-5 13-11 18-16l-20-31c-4-5-9-8-14-9-5-1-10 0-16 4-5 3-10 6-14 8-5 3-9 5-14 7-5 1-10 2-15 3-5 2-11 2-17 2-14 0-27-3-38-9-11-6-21-14-29-25-8-10-15-24-18-38-5-15-7-31-7-48-1-14 2-27 4-38z m336-102h-71l39 315h71l-39-315z m343 258h-80l-33-258h-70l32 258h-80l7 57h231l-7-57z" horiz-adv-x="1000" />
81 <glyph glyph-name="git" unicode="&#xe82a;" d="M929 844h-858c-36 0-65-30-65-65v-857c0-36 30-65 65-65h857c36 0 65 30 65 65v857c1 35-29 65-64 65z m-729-549c4-11 9-20 14-27 6-8 14-14 22-18 9-4 19-6 29-6 9 0 16 1 24 2 7 2 14 4 20 7l6 51h-27c-4 0-8 1-10 4-2 1-3 5-3 7l5 39h105l-16-131c-8-7-16-12-25-15-9-4-18-8-28-10-10-3-18-5-30-7-10-1-21-2-33-2-20 0-38 4-54 11-16 8-30 18-41 30-12 13-20 28-27 45-6 18-10 36-10 56 0 18 3 34 7 50 3 17 10 30 17 44 8 14 16 25 26 36 10 12 22 20 34 28 13 7 26 14 41 17 15 4 30 7 47 7 13 0 25-2 36-4 11-3 21-6 29-10 8-4 16-9 22-14 6-5 13-11 18-16l-20-31c-4-5-9-8-14-9-5-1-10 0-16 4-5 3-10 6-14 8-5 3-9 5-14 7-5 1-10 2-15 3-5 2-11 2-17 2-14 0-27-3-38-9-11-6-21-14-29-25-8-10-15-24-18-38-5-15-7-31-7-48-1-14 2-27 4-38z m336-102h-71l39 315h71l-39-315z m343 258h-80l-33-258h-70l32 258h-80l7 57h231l-7-57z" horiz-adv-x="1000" />
80
82
81 <glyph glyph-name="hg" unicode="&#xe82d;" d="M927 841h-853c-36 0-65-29-65-65v-853c0-36 29-65 65-65h853c36 0 65 29 65 65v853c0 36-29 65-65 65z m-483-648h-70l16 133h-113l-17-133h-70l39 313h70l-16-132h113l16 132h71l-39-313z m177 101c3-11 8-20 14-27 7-8 14-14 23-18 8-4 18-6 28-6 9 0 16 1 23 3 7 1 14 3 20 6l6 51h-27c-4 0-7 1-9 3-3 3-3 6-3 9l5 39h104l-16-131c-8-6-16-11-25-15-9-5-18-8-27-11-9-2-19-4-30-6-10-1-21-2-33-2-19 0-37 4-53 11-16 7-30 17-41 29-11 13-20 28-26 45-7 17-10 35-10 55 0 17 2 34 6 50 4 15 10 30 17 43 7 14 16 26 26 36 10 11 22 20 34 28 13 7 27 13 41 17 14 4 30 7 46 7 13 0 25-2 36-4 11-3 20-6 29-10 8-4 16-9 23-14 7-5 13-11 18-17l-23-28c-4-5-8-8-13-9-5-1-11 0-16 3-5 4-10 7-14 9-5 3-9 5-14 6-4 2-9 3-14 4-5 1-11 1-17 1-14 0-27-3-38-8-11-6-21-14-29-25-8-10-15-23-19-38-5-15-7-31-7-49 0-13 2-26 5-37z" horiz-adv-x="1000" />
83 <glyph glyph-name="hg" unicode="&#xe82d;" d="M927 841h-853c-36 0-65-29-65-65v-853c0-36 29-65 65-65h853c36 0 65 29 65 65v853c0 36-29 65-65 65z m-483-648h-70l16 133h-113l-17-133h-70l39 313h70l-16-132h113l16 132h71l-39-313z m177 101c3-11 8-20 14-27 7-8 14-14 23-18 8-4 18-6 28-6 9 0 16 1 23 3 7 1 14 3 20 6l6 51h-27c-4 0-7 1-9 3-3 3-3 6-3 9l5 39h104l-16-131c-8-6-16-11-25-15-9-5-18-8-27-11-9-2-19-4-30-6-10-1-21-2-33-2-19 0-37 4-53 11-16 7-30 17-41 29-11 13-20 28-26 45-7 17-10 35-10 55 0 17 2 34 6 50 4 15 10 30 17 43 7 14 16 26 26 36 10 11 22 20 34 28 13 7 27 13 41 17 14 4 30 7 46 7 13 0 25-2 36-4 11-3 20-6 29-10 8-4 16-9 23-14 7-5 13-11 18-17l-23-28c-4-5-8-8-13-9-5-1-11 0-16 3-5 4-10 7-14 9-5 3-9 5-14 6-4 2-9 3-14 4-5 1-11 1-17 1-14 0-27-3-38-8-11-6-21-14-29-25-8-10-15-23-19-38-5-15-7-31-7-49 0-13 2-26 5-37z" horiz-adv-x="1000" />
82
84
83 <glyph glyph-name="svn" unicode="&#xe82e;" d="M933 841h-852c-36 0-65-29-65-65v-853c0-36 29-65 65-65h852c36 0 66 29 66 65v853c0 36-30 65-66 65z m-765-438c3-4 7-7 13-10 5-3 11-6 18-8 7-3 14-5 21-8 7-3 14-6 21-10 7-4 13-9 18-14 5-6 10-13 13-20 3-8 5-18 5-29 0-16-3-30-8-44-6-14-14-26-24-37-10-10-22-18-37-24-15-7-31-10-49-10-9 0-18 1-27 3s-18 5-27 9c-8 4-16 8-23 13-7 5-13 10-18 17l25 32c2 3 4 5 7 6 3 2 6 3 9 3 4 0 8-2 12-4 3-3 8-6 12-10 5-3 10-6 16-9 6-3 14-4 23-4 13 0 23 3 30 10 7 7 10 18 10 32 0 6-1 12-4 16-4 4-8 7-13 10-5 3-11 6-18 8-7 2-14 5-21 7-7 3-14 6-21 9-6 4-12 8-18 14-5 6-9 13-12 21-3 8-5 18-5 30 0 14 3 28 8 40 5 13 12 25 22 35 10 9 22 17 36 23 14 6 29 9 47 9 9 0 17-1 26-3s16-4 23-8c7-3 14-7 20-11 6-5 11-10 15-15l-21-29c-2-3-5-6-7-7-3-2-6-3-9-3-3 0-7 1-10 3-3 3-7 5-11 8-4 2-9 4-14 7-5 2-12 3-19 3-6 0-12-1-17-3-5-2-9-4-12-8-4-3-6-7-8-11-1-5-2-10-2-15 0-5 2-10 5-14z m312-210h-64l-77 313h57c6 0 10-1 14-4 4-3 6-6 7-11l32-173c2-7 4-14 6-23 1-8 3-17 4-26 3 9 6 18 9 26 4 9 7 16 11 23l73 173c1 2 2 4 4 6 2 2 4 3 6 5 2 1 4 2 7 3 3 1 5 1 8 1h57l-154-313z m423 0h-37c-5 0-10 1-13 2-4 2-7 5-10 9l-109 194c-1-4-1-8-1-12-1-4-1-7-1-10l-22-183h-62l39 313h37c3 0 6 0 8 0 2 0 4-1 5-1 2-1 3-2 4-4s3-3 5-5l110-194c0 5 0 10 1 14 0 5 1 9 1 13l21 177h62l-38-313z" horiz-adv-x="1000" />
85 <glyph glyph-name="svn" unicode="&#xe82e;" d="M933 841h-852c-36 0-65-29-65-65v-853c0-36 29-65 65-65h852c36 0 66 29 66 65v853c0 36-30 65-66 65z m-765-438c3-4 7-7 13-10 5-3 11-6 18-8 7-3 14-5 21-8 7-3 14-6 21-10 7-4 13-9 18-14 5-6 10-13 13-20 3-8 5-18 5-29 0-16-3-30-8-44-6-14-14-26-24-37-10-10-22-18-37-24-15-7-31-10-49-10-9 0-18 1-27 3s-18 5-27 9c-8 4-16 8-23 13-7 5-13 10-18 17l25 32c2 3 4 5 7 6 3 2 6 3 9 3 4 0 8-2 12-4 3-3 8-6 12-10 5-3 10-6 16-9 6-3 14-4 23-4 13 0 23 3 30 10 7 7 10 18 10 32 0 6-1 12-4 16-4 4-8 7-13 10-5 3-11 6-18 8-7 2-14 5-21 7-7 3-14 6-21 9-6 4-12 8-18 14-5 6-9 13-12 21-3 8-5 18-5 30 0 14 3 28 8 40 5 13 12 25 22 35 10 9 22 17 36 23 14 6 29 9 47 9 9 0 17-1 26-3s16-4 23-8c7-3 14-7 20-11 6-5 11-10 15-15l-21-29c-2-3-5-6-7-7-3-2-6-3-9-3-3 0-7 1-10 3-3 3-7 5-11 8-4 2-9 4-14 7-5 2-12 3-19 3-6 0-12-1-17-3-5-2-9-4-12-8-4-3-6-7-8-11-1-5-2-10-2-15 0-5 2-10 5-14z m312-210h-64l-77 313h57c6 0 10-1 14-4 4-3 6-6 7-11l32-173c2-7 4-14 6-23 1-8 3-17 4-26 3 9 6 18 9 26 4 9 7 16 11 23l73 173c1 2 2 4 4 6 2 2 4 3 6 5 2 1 4 2 7 3 3 1 5 1 8 1h57l-154-313z m423 0h-37c-5 0-10 1-13 2-4 2-7 5-10 9l-109 194c-1-4-1-8-1-12-1-4-1-7-1-10l-22-183h-62l39 313h37c3 0 6 0 8 0 2 0 4-1 5-1 2-1 3-2 4-4s3-3 5-5l110-194c0 5 0 10 1 14 0 5 1 9 1 13l21 177h62l-38-313z" horiz-adv-x="1000" />
84
86
85 <glyph glyph-name="comment-add" unicode="&#xe82f;" d="M952 258v317c0 7 0 13 0 20-1 12-4 24-8 36-7 22-20 43-37 59-16 17-36 30-58 37-12 4-25 7-37 8-7 1-13 1-19 1h-576c-13 0-26 0-38-2-13-2-25-5-36-10-22-9-41-23-57-40-15-18-27-39-33-62-3-12-5-25-5-38-1-13 0-26 0-39v-557c0-9 5-17 13-21 6-3 15-3 21 0 3 1 5 3 7 5 2 2 4 5 7 7 4 5 9 9 14 14l28 28c9 10 19 19 28 29 9 9 19 18 28 27 4 5 8 9 14 10 2 1 5 1 8 1h567c13 0 25 0 38 2 24 4 47 13 66 27 19 13 35 31 46 51 12 22 19 46 19 71 1 6 0 13 0 19z m-69 307v-317c0-7 0-13 0-19-1-6-3-13-5-18-4-10-9-20-16-28-15-17-37-27-59-28-7 0-13 0-19 0h-576c-7 0-13 0-20 0-3 0-6 0-9-1-3-1-5-2-7-4-2-2-4-4-6-6-3-2-5-4-7-7-5-4-10-9-14-14-10-9-19-18-28-28v485c0 12 2 24 7 35 4 10 10 19 18 27 16 16 38 25 60 25h590c6 0 12 0 18-1 22-3 42-15 56-33 7-9 12-20 15-31 1-5 2-12 2-18 1-6 0-13 0-19z m-214-117h-131c-4 0-11 8-11 12v126c0 8-8 16-12 16h-50c-7 0-15-8-15-12v-130c0-4-8-12-12-12h-126c-8 0-16-8-16-11v-50c0-8 8-16 12-16h127c7 0 15-7 15-11v-127c0-8 8-15 11-15h50c8 0 16 7 16 11v127c0 8 7 15 11 15h127c8 0 15 8 15 12v50c0 7-7 15-11 15z" horiz-adv-x="1000" />
87 <glyph glyph-name="comment-add" unicode="&#xe82f;" d="M952 258v317c0 7 0 13 0 20-1 12-4 24-8 36-7 22-20 43-37 59-16 17-36 30-58 37-12 4-25 7-37 8-7 1-13 1-19 1h-576c-13 0-26 0-38-2-13-2-25-5-36-10-22-9-41-23-57-40-15-18-27-39-33-62-3-12-5-25-5-38-1-13 0-26 0-39v-557c0-9 5-17 13-21 6-3 15-3 21 0 3 1 5 3 7 5 2 2 4 5 7 7 4 5 9 9 14 14l28 28c9 10 19 19 28 29 9 9 19 18 28 27 4 5 8 9 14 10 2 1 5 1 8 1h567c13 0 25 0 38 2 24 4 47 13 66 27 19 13 35 31 46 51 12 22 19 46 19 71 1 6 0 13 0 19z m-69 307v-317c0-7 0-13 0-19-1-6-3-13-5-18-4-10-9-20-16-28-15-17-37-27-59-28-7 0-13 0-19 0h-576c-7 0-13 0-20 0-3 0-6 0-9-1-3-1-5-2-7-4-2-2-4-4-6-6-3-2-5-4-7-7-5-4-10-9-14-14-10-9-19-18-28-28v485c0 12 2 24 7 35 4 10 10 19 18 27 16 16 38 25 60 25h590c6 0 12 0 18-1 22-3 42-15 56-33 7-9 12-20 15-31 1-5 2-12 2-18 1-6 0-13 0-19z m-214-117h-131c-4 0-11 8-11 12v126c0 8-8 16-12 16h-50c-7 0-15-8-15-12v-130c0-4-8-12-12-12h-126c-8 0-16-8-16-11v-50c0-8 8-16 12-16h127c7 0 15-7 15-11v-127c0-8 8-15 11-15h50c8 0 16 7 16 11v127c0 8 7 15 11 15h127c8 0 15 8 15 12v50c0 7-7 15-11 15z" horiz-adv-x="1000" />
86
88
87 <glyph glyph-name="comment-toggle" unicode="&#xe830;" d="M798 736h-596c-85 0-154-69-154-155v-593c0-19 22-29 36-20 2 1 5 3 7 5l109 109c2 2 5 4 8 5 2 1 4 1 6 1h584c85 0 154 69 154 155v338c0 86-69 155-154 155z m-680-639v484c0 47 38 85 86 85h476c-86-84-504-511-509-515l-53-54z" horiz-adv-x="1000" />
89 <glyph glyph-name="comment-toggle" unicode="&#xe830;" d="M798 736h-596c-85 0-154-69-154-155v-593c0-19 22-29 36-20 2 1 5 3 7 5l109 109c2 2 5 4 8 5 2 1 4 1 6 1h584c85 0 154 69 154 155v338c0 86-69 155-154 155z m-680-639v484c0 47 38 85 86 85h476c-86-84-504-511-509-515l-53-54z" horiz-adv-x="1000" />
88
90
89 <glyph glyph-name="rhodecode" unicode="&#xe831;" d="M175 633c-2-4-3-8-4-12-3-10-6-20-9-30-3-13-7-25-11-38-3-11-6-23-10-35-2-7-4-15-6-22-1-1-1-2-1-4 0 0 0 0 0 0 0-1 1-2 1-2 2-7 5-14 7-21 4-11 8-22 12-33 4-12 9-25 13-37 4-11 8-23 12-34 3-7 5-14 7-21 1-1 1-2 2-3 0-1 1-1 1-2 4-6 8-12 11-17 7-10 13-19 19-29 7-11 14-22 22-33 6-10 13-21 20-31 5-7 9-15 14-22 1-2 3-4 4-5 0-1 1-1 1-2 3-3 6-5 8-8 7-6 13-12 19-19 9-8 17-16 25-24 10-10 19-19 29-28 9-9 18-18 27-27 8-8 16-15 23-23 5-5 11-10 16-15 1-1 3-3 5-5 7-5 14-10 21-15 11-8 21-15 31-23 4-2 7-5 11-7 0-1 1-2 2-2 0 0 0-1 1 0 7 3 14 7 21 11 11 6 23 11 34 17 6 4 12 7 19 10 0 0 0 1 1 1 1 2 2 3 3 5 4 5 8 10 13 15 6 8 12 16 18 24 8 9 15 19 23 28 8 11 16 21 24 31 8 11 16 21 24 31 8 10 15 19 23 28 6 8 12 16 18 24 4 5 8 10 12 15 2 2 3 3 4 5 0 0 0 0 0 0-1 1-2 1-3 1-3 0-6 1-9 2-5 1-10 2-15 3-6 2-13 4-20 5-8 3-16 5-24 7-9 3-19 6-28 9-10 3-21 7-31 11-12 4-23 8-34 13-12 5-24 10-36 15-13 6-26 12-38 18-13 7-26 14-39 21-13 7-27 15-39 23-14 9-27 17-40 27-13 9-26 19-39 29-13 11-25 22-37 33-13 11-25 23-36 36-12 13-23 26-34 40-11 14-21 28-31 43-9 15-19 31-27 47 0 1 0 1 0 1z m-3 3c-1-5-3-9-4-14-3-10-7-21-10-32-4-12-8-25-12-37-3-10-6-20-9-30-1-3-2-6-3-8 0-1 0-2 0-2 1-5 3-10 5-15 3-10 6-20 10-30 4-12 8-24 12-37 4-12 8-24 12-36 3-9 6-18 9-26 1-3 1-5 2-8 0 0 1-1 1-2 2-4 5-8 7-12 5-10 10-19 15-28 6-11 12-23 19-34 6-11 12-22 18-33 4-8 8-15 12-23 1-2 2-4 4-6 4-5 8-9 13-14 7-8 15-16 23-24 9-10 18-20 26-29 9-9 17-18 25-26 5-6 10-11 15-17 2-1 3-3 5-5 5-5 11-11 17-17 9-8 17-17 26-26 9-9 18-18 27-27 7-7 14-14 21-21 2-2 3-3 5-5 0 0 1-1 1-1 0 0 1 0 1 0 11 2 22 3 32 5 9 1 17 2 26 3 0 0 1 1 1 1 1 1 2 3 4 4 4 5 9 10 13 15 7 8 14 15 20 22 9 9 17 18 25 27 9 10 18 20 27 30 8 9 17 19 26 29 8 9 16 17 24 26 7 7 13 15 20 22 4 5 8 9 13 14 1 1 2 2 3 3 0 1 1 1 1 1 0 1-3 1-3 1-3 1-7 2-10 3-4 2-9 3-14 5-6 2-13 4-19 6-8 3-16 6-24 9-9 3-18 7-27 11-10 4-20 8-30 13-11 5-22 10-33 16-12 5-23 11-35 18-12 6-24 13-36 20-12 8-25 16-37 24-13 8-25 17-37 26-13 10-25 19-38 29-12 11-24 21-36 33-12 11-24 23-35 35-11 13-22 25-33 39-10 13-21 27-30 42-10 15-19 30-27 45-9 16-17 32-24 48z m-2 10c-1-4-2-8-3-11-1-10-3-19-5-29-2-12-5-25-7-37-3-13-5-26-8-39-1-10-3-20-5-30-1-5-2-10-3-15 0-1 0-1 0-2 1-3 2-5 3-8 3-9 7-19 10-29 4-12 9-25 13-37 4-11 8-22 11-33 2-5 4-11 6-16 0-1 1-2 1-2 1-3 2-5 4-7 4-9 8-18 13-27 6-12 11-23 17-35 6-11 11-22 17-33 3-7 7-14 11-21 0-2 1-3 1-4 1-1 2-1 2-2 5-6 9-11 14-17 8-9 15-18 22-27 9-10 17-20 26-30 7-9 15-18 22-27 5-6 10-11 15-17 0-1 1-2 2-3 0 0 0 0 0 0 1-1 2-1 3-2 7-4 14-9 21-14 10-7 21-14 31-22 11-7 21-14 31-20 6-4 12-9 18-13 3-2 7-5 10-8 10-8 19-16 29-24 7-5 13-11 20-17 1 0 1 0 1 1 1 1 2 2 3 3 4 4 8 8 12 13 6 6 12 13 18 20 8 8 16 17 23 25 9 10 18 19 26 29 9 9 18 19 27 29 9 9 18 19 26 28 8 9 16 17 23 26 6 6 13 13 19 20 4 4 7 8 11 12 1 2 3 3 4 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0-3 1-3 1-3 1-6 2-9 2-5 2-10 4-15 5-6 2-12 5-18 7-8 3-16 6-24 9-8 4-17 8-26 12-10 4-20 9-30 13-11 6-22 11-32 16-12 6-23 13-35 19-12 7-23 14-35 21-13 8-25 16-37 24-12 8-25 17-37 26-12 9-24 19-36 29-13 10-25 21-36 32-12 11-24 22-35 34-12 12-22 25-33 38-11 13-21 26-30 40-10 14-19 29-28 44-9 15-17 30-24 46-4 10-8 20-12 30z m696 21c-2 4-5 7-9 9-5 3-11 5-16 8-11 4-23 9-34 13-23 8-47 14-71 20-24 6-49 12-74 17-25 6-50 10-76 15-25 4-50 8-75 10-13 1-26 1-39 0-6-1-13-2-19-3-6-1-13-2-19-3-26-4-51-9-77-14-25-5-50-10-75-16-25-5-49-12-74-20-12-4-24-9-36-13-6-3-11-5-17-8-3-1-6-2-9-3-3-1-5-2-8-4-4-2-7-5-10-9-1-2-2-4-3-7-1-3-2-6-3-9-4-11-7-24-9-36-5-24-7-49-6-74 0-13 1-25 3-38 1-12 3-25 5-37 5-25 12-50 20-74 4-12 8-24 13-36 4-11 10-22 15-33 10-21 21-42 34-62 12-20 25-39 39-58 14-19 28-37 43-55 16-18 33-36 50-54 17-18 34-35 52-52 18-17 36-33 55-49 10-7 19-15 28-22 10-8 19-15 28-23 2-2 5-4 7-7 0 0 1-1 1-1 0 0 1 0 1 0 0 0 1 0 2 0 4 4 9 8 14 11 9 8 19 15 28 23 18 15 36 31 54 47 18 16 35 32 52 49 17 16 33 34 49 51 16 18 32 37 47 56 14 18 28 38 41 57 13 20 25 40 36 61 11 21 21 43 30 65 9 22 17 45 23 68 6 23 11 47 13 70 3 24 3 49 2 73 0 3-1 6-2 9 0 3-1 6-2 9-1 6-2 12-3 18-3 11-5 22-8 33-4 9-7 19-11 28-2 5 13-29 0 0z m-51-210c-7-25-15-49-26-73-9-22-19-44-30-64-12-21-24-40-37-59-13-19-27-38-42-56-15-18-31-36-47-54-17-18-34-36-52-53-18-17-37-34-56-50-9-7-19-15-28-23-1 0-2-1-2-1-1 0-2 0-2 0-1 0-2 1-2 1 0 0-1 1-1 1-2 1-3 3-4 4-4 3-9 7-14 11-2 1-4 3-7 5-2 2-4 4-6 6-5 4-9 8-14 13-9 8-18 17-27 25-10 9-18 18-27 27-4 4-8 9-13 13-4 4-8 9-12 13-17 17-33 35-49 53-15 18-30 37-44 57-14 20-27 40-38 61-12 21-23 42-32 64-10 22-18 45-25 67-2 6-4 12-5 19-1 6-2 12-3 19-2 13-4 26-4 39-1 13-2 26-1 39 0 12 1 25 3 37 0 4 0 7 1 10 0 1 0 3 0 5 1 1 1 3 1 4 0 3 1 5 2 7 0 2 0 3 0 4 0 1 1 2 2 3 1 0 2 1 3 2 0 0 1 0 1 1 1 0 2 0 3 1 3 1 6 2 9 3 6 2 12 5 18 7 23 8 47 16 72 23 12 3 24 6 37 9 6 1 12 2 18 4 7 1 13 2 19 4 26 5 51 9 77 13 13 1 26 3 39 5 3 0 7 1 10 1 1 1 3 1 4 1 2 0 3 0 4 0 6 0 12 0 17-1 1 0 2-1 4-1 1 0 3-1 4-1 3 0 6-1 9-1 7-1 13-2 19-3 13-2 25-4 38-6 25-4 51-8 76-13 25-6 50-12 75-19 12-4 24-8 37-12 6-2 12-4 18-6 3-1 6-2 9-3 1-1 3-1 4-2 1 0 1 0 2 0 1-1 2-1 2-1 2-2 3-2 4-4 1-1 1-1 1-2 0-1 0-2 0-2 1-1 1-2 1-3 2-6 3-13 4-19 1-7 2-13 3-20 0-3 0-6 0-9 0-1 0-2 0-2 0-1 0-2 0-3 1-1 1-3 1-5 5-23 7-48 5-72-1-13-3-26-6-38-8-29 8 35 0 0z m-197 0c-2 4-3 9-5 13 0 1 0 1 0 2-1 0 0 1-1 1 0 1 0 2 0 2 0 1-1 2-1 3-1 2-3 4-4 5-2 2-5 4-7 4 2 2 4 3 7 5 1 1 2 2 3 2 1 1 2 1 2 2 0 1 0 1 0 2 1 0 1 1 2 1 0 1 1 2 1 4 0 2 0 4 0 6 0 3 0 5 0 7 0 3 0 5-1 7-1 6-4 10-8 14-1 2-3 3-5 4-3 2-5 4-8 5-3 1-6 2-9 3-3 0-5 0-7 0-3 0-6 0-8 0-13 0-25 0-37 0-5 0-10 0-14 0-1 0-2 0-3 0 0 0 0-4 0-5 0-3 0-6 0-9 0-1 0-2 0-3 0-1 0-1 1-1 1 0 12 0 12 0 0-8 0-16 0-24 0-13 0-25 0-38 0-4 0-7 0-11 0 0 0-1 0-1-3 0-5 0-8 0-1 0-2 0-4 0 0 0-1 0-1-1 0-2 0-4 0-6 0-1 0-14 0-14 10 0 19 0 29 0 5 0 11 0 16 0 1 0 3 0 4 0 0 0 0 3 0 3 0 6 0 11 0 17 0 1 0 1-1 1-1 0-2 0-4 0-1 0-3 0-4 0 0 0-1-1-1 0 0 5 0 10 0 15 0 2 0 5 0 8 0 1 0 1 0 2 0 0 0 0 1 0 2 0 5 0 8 0 2 0 4 0 6 0 1 0 3 0 4 0 1 0 2-1 3-2 1-1 2-2 3-3 0-1 0-1 0-2 0-2 1-3 1-4 1-1 1-2 2-3 0-1 0-1 0-1 0-1 0-2 0-2 1-6 2-12 3-17 1-3 1-5 2-8 0 0 0-1 0-1 0 0 0 0 0 0 11 0 21 0 32 0 0 0 1 0 1 0 0 0 0 0 0 0 0 3 0 5 0 8 0 5 0 10 0 15 0 0 0 0 0 0-1-2-1-4-2-5z m-26 53c0-2-3-3-4-4-1 0-1-1-1-1 0 0-1 0-1 0 0 0-1 0-1 0-1-1-1-2-2-2-1 0-2 0-3 0-2 0-4 0-5 0-1 0-2 0-2 0-3 0-7 0-10 0 0 0-4 0-4 0 0 9 0 19 0 28 0 0 13 0 14 0 4 0 8 0 12-1 1 0 3-1 4-2 1 0 2-1 3-2 1-2 2-4 3-6 0-1 0-1 0-2-1-1-1-1-1-2-1-1-1-1-1-2-1-1-1-2-1-4z m131-53c0 9 0 18 0 27 0 9-2 18-8 24-7 7-19 8-28 7-2 0-4 0-6-1-1 0-1-1-2-2-1 0-2 0-2-1-3-1-6-3-8-6 0 9 0 18 0 27 0 6 0 12 0 18 0 2 0 3 0 5 0 1 0 1 0 1-11 0-22 0-32 0-1 0-3 0-4 0 0 0 0-4 0-4 0-5 0-11 0-16 0 0 1 0 1 0 1 0 3 0 4 0 3 0 5 0 8 0 0 0 0-5 0-6 0-11 0-23 0-34 0-11 0-22 0-33 0-1 0-2 0-3 0-1 0-1-1-1-3 0-6 0-9 0-1 0-2 0-3 0 0 0 0-1 0-1 0-6 0-11 0-17 0-1 0-1 0-2 0 0 0 0 0 0 2 0 3 0 4 0 12 0 24 0 36 0 0 0 9 0 9 0 0 5 0 10 0 15 0 1 0 3 0 5 0 0-6 0-7 0 0 0-6 0-6 0 0 1 0 3 0 4 0 6 0 12 0 18 0 3 0 5 0 7 0 1 0 1 0 2 0 0 1 1 2 2 1 1 2 2 3 2 1 1 1 1 2 1 1 0 1 0 1 1 2 1 3 1 4 1 3 1 5 0 7-1 1-1 2-2 3-3 1-1 2-2 2-3 1-2 1-4 1-6 0-3 0-7 0-11 0-11 0-22 0-33 0-1 0-2 1-2 1 0 3 0 5 0 6 0 12 0 19 0 3 0 7 0 11 0 0 0 0 14 0 15 0 2 0 4 0 6-2-1-5-2-7-2z m7 122c-2 0-5 0-7 0-1 0-2 0-3 0 0 0 0 0 0 0-3-5-7-10-10-14-1-2-3-5-4-7 0 0-1-1-1-2 0 0 0-1 0-1 0-1 0-4 0-4 0 0 1 0 2 0 3 0 5 0 8 0 3 0 5 0 8 0 0 0 0-1 0-1 0-1 0-3 0-4 0-2 0-3 0-4 0-1 0-1 1-1 1 0 3 0 4 0 1 0 2 0 2 0 0 3 0 6 0 8 0 1 0 2 1 2 1 0 2 0 4 0 0 0 0 0 0 0 0 1 0 1 0 2 0 0 0 3 0 3-1 0-2 0-3 0-1 0-2 0-2 1 0 7 0 15 0 22z m-7-15c0-1 0-2 0-4 0-1 0-1 0-2 0 0 0-1 0-2 0 0-1 0-1 0-1 0-2 0-3 0-1 0-3 0-4 0 1 2 3 4 4 6 1 1 1 2 2 3 1 2 2 4 2 7 0-3 0-5 0-8z m41-2c-3 2-8 2-11 2-1 0-2 0-2 0 0 0 0 1 0 1 0 2 0 3 0 4 0 0 13 0 14 0 1 0 1 0 1 1 0 1 0 2 0 4 0 1 0 2 0 3 0 0-1 0-1 0-6 0-11 0-17 0-1 0-1 0-2 0 0 0 0-1 0-1-1-2-1-4-1-6-1-5-1-9-2-14 4 0 9 1 12-1 3-1 4-4 4-7-1-4-5-4-7-4-2 0-9-1-9 2-1-2-1-5-2-8 1 0 3-1 5-1 2-1 5-1 7-1 4 0 8 2 11 5 2 3 2 7 2 11 0 2 0 5 0 7 0 1-1 2-2 3 0 0 0 0 0 0-3 2 2 0 0 0z" horiz-adv-x="1000" />
91 <glyph glyph-name="rhodecode" unicode="&#xe831;" d="M175 633c-2-4-3-8-4-12-3-10-6-20-9-30-3-13-7-25-11-38-3-11-6-23-10-35-2-7-4-15-6-22-1-1-1-2-1-4 0 0 0 0 0 0 0-1 1-2 1-2 2-7 5-14 7-21 4-11 8-22 12-33 4-12 9-25 13-37 4-11 8-23 12-34 3-7 5-14 7-21 1-1 1-2 2-3 0-1 1-1 1-2 4-6 8-12 11-17 7-10 13-19 19-29 7-11 14-22 22-33 6-10 13-21 20-31 5-7 9-15 14-22 1-2 3-4 4-5 0-1 1-1 1-2 3-3 6-5 8-8 7-6 13-12 19-19 9-8 17-16 25-24 10-10 19-19 29-28 9-9 18-18 27-27 8-8 16-15 23-23 5-5 11-10 16-15 1-1 3-3 5-5 7-5 14-10 21-15 11-8 21-15 31-23 4-2 7-5 11-7 0-1 1-2 2-2 0 0 0-1 1 0 7 3 14 7 21 11 11 6 23 11 34 17 6 4 12 7 19 10 0 0 0 1 1 1 1 2 2 3 3 5 4 5 8 10 13 15 6 8 12 16 18 24 8 9 15 19 23 28 8 11 16 21 24 31 8 11 16 21 24 31 8 10 15 19 23 28 6 8 12 16 18 24 4 5 8 10 12 15 2 2 3 3 4 5 0 0 0 0 0 0-1 1-2 1-3 1-3 0-6 1-9 2-5 1-10 2-15 3-6 2-13 4-20 5-8 3-16 5-24 7-9 3-19 6-28 9-10 3-21 7-31 11-12 4-23 8-34 13-12 5-24 10-36 15-13 6-26 12-38 18-13 7-26 14-39 21-13 7-27 15-39 23-14 9-27 17-40 27-13 9-26 19-39 29-13 11-25 22-37 33-13 11-25 23-36 36-12 13-23 26-34 40-11 14-21 28-31 43-9 15-19 31-27 47 0 1 0 1 0 1z m-3 3c-1-5-3-9-4-14-3-10-7-21-10-32-4-12-8-25-12-37-3-10-6-20-9-30-1-3-2-6-3-8 0-1 0-2 0-2 1-5 3-10 5-15 3-10 6-20 10-30 4-12 8-24 12-37 4-12 8-24 12-36 3-9 6-18 9-26 1-3 1-5 2-8 0 0 1-1 1-2 2-4 5-8 7-12 5-10 10-19 15-28 6-11 12-23 19-34 6-11 12-22 18-33 4-8 8-15 12-23 1-2 2-4 4-6 4-5 8-9 13-14 7-8 15-16 23-24 9-10 18-20 26-29 9-9 17-18 25-26 5-6 10-11 15-17 2-1 3-3 5-5 5-5 11-11 17-17 9-8 17-17 26-26 9-9 18-18 27-27 7-7 14-14 21-21 2-2 3-3 5-5 0 0 1-1 1-1 0 0 1 0 1 0 11 2 22 3 32 5 9 1 17 2 26 3 0 0 1 1 1 1 1 1 2 3 4 4 4 5 9 10 13 15 7 8 14 15 20 22 9 9 17 18 25 27 9 10 18 20 27 30 8 9 17 19 26 29 8 9 16 17 24 26 7 7 13 15 20 22 4 5 8 9 13 14 1 1 2 2 3 3 0 1 1 1 1 1 0 1-3 1-3 1-3 1-7 2-10 3-4 2-9 3-14 5-6 2-13 4-19 6-8 3-16 6-24 9-9 3-18 7-27 11-10 4-20 8-30 13-11 5-22 10-33 16-12 5-23 11-35 18-12 6-24 13-36 20-12 8-25 16-37 24-13 8-25 17-37 26-13 10-25 19-38 29-12 11-24 21-36 33-12 11-24 23-35 35-11 13-22 25-33 39-10 13-21 27-30 42-10 15-19 30-27 45-9 16-17 32-24 48z m-2 10c-1-4-2-8-3-11-1-10-3-19-5-29-2-12-5-25-7-37-3-13-5-26-8-39-1-10-3-20-5-30-1-5-2-10-3-15 0-1 0-1 0-2 1-3 2-5 3-8 3-9 7-19 10-29 4-12 9-25 13-37 4-11 8-22 11-33 2-5 4-11 6-16 0-1 1-2 1-2 1-3 2-5 4-7 4-9 8-18 13-27 6-12 11-23 17-35 6-11 11-22 17-33 3-7 7-14 11-21 0-2 1-3 1-4 1-1 2-1 2-2 5-6 9-11 14-17 8-9 15-18 22-27 9-10 17-20 26-30 7-9 15-18 22-27 5-6 10-11 15-17 0-1 1-2 2-3 0 0 0 0 0 0 1-1 2-1 3-2 7-4 14-9 21-14 10-7 21-14 31-22 11-7 21-14 31-20 6-4 12-9 18-13 3-2 7-5 10-8 10-8 19-16 29-24 7-5 13-11 20-17 1 0 1 0 1 1 1 1 2 2 3 3 4 4 8 8 12 13 6 6 12 13 18 20 8 8 16 17 23 25 9 10 18 19 26 29 9 9 18 19 27 29 9 9 18 19 26 28 8 9 16 17 23 26 6 6 13 13 19 20 4 4 7 8 11 12 1 2 3 3 4 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0-3 1-3 1-3 1-6 2-9 2-5 2-10 4-15 5-6 2-12 5-18 7-8 3-16 6-24 9-8 4-17 8-26 12-10 4-20 9-30 13-11 6-22 11-32 16-12 6-23 13-35 19-12 7-23 14-35 21-13 8-25 16-37 24-12 8-25 17-37 26-12 9-24 19-36 29-13 10-25 21-36 32-12 11-24 22-35 34-12 12-22 25-33 38-11 13-21 26-30 40-10 14-19 29-28 44-9 15-17 30-24 46-4 10-8 20-12 30z m696 21c-2 4-5 7-9 9-5 3-11 5-16 8-11 4-23 9-34 13-23 8-47 14-71 20-24 6-49 12-74 17-25 6-50 10-76 15-25 4-50 8-75 10-13 1-26 1-39 0-6-1-13-2-19-3-6-1-13-2-19-3-26-4-51-9-77-14-25-5-50-10-75-16-25-5-49-12-74-20-12-4-24-9-36-13-6-3-11-5-17-8-3-1-6-2-9-3-3-1-5-2-8-4-4-2-7-5-10-9-1-2-2-4-3-7-1-3-2-6-3-9-4-11-7-24-9-36-5-24-7-49-6-74 0-13 1-25 3-38 1-12 3-25 5-37 5-25 12-50 20-74 4-12 8-24 13-36 4-11 10-22 15-33 10-21 21-42 34-62 12-20 25-39 39-58 14-19 28-37 43-55 16-18 33-36 50-54 17-18 34-35 52-52 18-17 36-33 55-49 10-7 19-15 28-22 10-8 19-15 28-23 2-2 5-4 7-7 0 0 1-1 1-1 0 0 1 0 1 0 0 0 1 0 2 0 4 4 9 8 14 11 9 8 19 15 28 23 18 15 36 31 54 47 18 16 35 32 52 49 17 16 33 34 49 51 16 18 32 37 47 56 14 18 28 38 41 57 13 20 25 40 36 61 11 21 21 43 30 65 9 22 17 45 23 68 6 23 11 47 13 70 3 24 3 49 2 73 0 3-1 6-2 9 0 3-1 6-2 9-1 6-2 12-3 18-3 11-5 22-8 33-4 9-7 19-11 28-2 5 13-29 0 0z m-51-210c-7-25-15-49-26-73-9-22-19-44-30-64-12-21-24-40-37-59-13-19-27-38-42-56-15-18-31-36-47-54-17-18-34-36-52-53-18-17-37-34-56-50-9-7-19-15-28-23-1 0-2-1-2-1-1 0-2 0-2 0-1 0-2 1-2 1 0 0-1 1-1 1-2 1-3 3-4 4-4 3-9 7-14 11-2 1-4 3-7 5-2 2-4 4-6 6-5 4-9 8-14 13-9 8-18 17-27 25-10 9-18 18-27 27-4 4-8 9-13 13-4 4-8 9-12 13-17 17-33 35-49 53-15 18-30 37-44 57-14 20-27 40-38 61-12 21-23 42-32 64-10 22-18 45-25 67-2 6-4 12-5 19-1 6-2 12-3 19-2 13-4 26-4 39-1 13-2 26-1 39 0 12 1 25 3 37 0 4 0 7 1 10 0 1 0 3 0 5 1 1 1 3 1 4 0 3 1 5 2 7 0 2 0 3 0 4 0 1 1 2 2 3 1 0 2 1 3 2 0 0 1 0 1 1 1 0 2 0 3 1 3 1 6 2 9 3 6 2 12 5 18 7 23 8 47 16 72 23 12 3 24 6 37 9 6 1 12 2 18 4 7 1 13 2 19 4 26 5 51 9 77 13 13 1 26 3 39 5 3 0 7 1 10 1 1 1 3 1 4 1 2 0 3 0 4 0 6 0 12 0 17-1 1 0 2-1 4-1 1 0 3-1 4-1 3 0 6-1 9-1 7-1 13-2 19-3 13-2 25-4 38-6 25-4 51-8 76-13 25-6 50-12 75-19 12-4 24-8 37-12 6-2 12-4 18-6 3-1 6-2 9-3 1-1 3-1 4-2 1 0 1 0 2 0 1-1 2-1 2-1 2-2 3-2 4-4 1-1 1-1 1-2 0-1 0-2 0-2 1-1 1-2 1-3 2-6 3-13 4-19 1-7 2-13 3-20 0-3 0-6 0-9 0-1 0-2 0-2 0-1 0-2 0-3 1-1 1-3 1-5 5-23 7-48 5-72-1-13-3-26-6-38-8-29 8 35 0 0z m-197 0c-2 4-3 9-5 13 0 1 0 1 0 2-1 0 0 1-1 1 0 1 0 2 0 2 0 1-1 2-1 3-1 2-3 4-4 5-2 2-5 4-7 4 2 2 4 3 7 5 1 1 2 2 3 2 1 1 2 1 2 2 0 1 0 1 0 2 1 0 1 1 2 1 0 1 1 2 1 4 0 2 0 4 0 6 0 3 0 5 0 7 0 3 0 5-1 7-1 6-4 10-8 14-1 2-3 3-5 4-3 2-5 4-8 5-3 1-6 2-9 3-3 0-5 0-7 0-3 0-6 0-8 0-13 0-25 0-37 0-5 0-10 0-14 0-1 0-2 0-3 0 0 0 0-4 0-5 0-3 0-6 0-9 0-1 0-2 0-3 0-1 0-1 1-1 1 0 12 0 12 0 0-8 0-16 0-24 0-13 0-25 0-38 0-4 0-7 0-11 0 0 0-1 0-1-3 0-5 0-8 0-1 0-2 0-4 0 0 0-1 0-1-1 0-2 0-4 0-6 0-1 0-14 0-14 10 0 19 0 29 0 5 0 11 0 16 0 1 0 3 0 4 0 0 0 0 3 0 3 0 6 0 11 0 17 0 1 0 1-1 1-1 0-2 0-4 0-1 0-3 0-4 0 0 0-1-1-1 0 0 5 0 10 0 15 0 2 0 5 0 8 0 1 0 1 0 2 0 0 0 0 1 0 2 0 5 0 8 0 2 0 4 0 6 0 1 0 3 0 4 0 1 0 2-1 3-2 1-1 2-2 3-3 0-1 0-1 0-2 0-2 1-3 1-4 1-1 1-2 2-3 0-1 0-1 0-1 0-1 0-2 0-2 1-6 2-12 3-17 1-3 1-5 2-8 0 0 0-1 0-1 0 0 0 0 0 0 11 0 21 0 32 0 0 0 1 0 1 0 0 0 0 0 0 0 0 3 0 5 0 8 0 5 0 10 0 15 0 0 0 0 0 0-1-2-1-4-2-5z m-26 53c0-2-3-3-4-4-1 0-1-1-1-1 0 0-1 0-1 0 0 0-1 0-1 0-1-1-1-2-2-2-1 0-2 0-3 0-2 0-4 0-5 0-1 0-2 0-2 0-3 0-7 0-10 0 0 0-4 0-4 0 0 9 0 19 0 28 0 0 13 0 14 0 4 0 8 0 12-1 1 0 3-1 4-2 1 0 2-1 3-2 1-2 2-4 3-6 0-1 0-1 0-2-1-1-1-1-1-2-1-1-1-1-1-2-1-1-1-2-1-4z m131-53c0 9 0 18 0 27 0 9-2 18-8 24-7 7-19 8-28 7-2 0-4 0-6-1-1 0-1-1-2-2-1 0-2 0-2-1-3-1-6-3-8-6 0 9 0 18 0 27 0 6 0 12 0 18 0 2 0 3 0 5 0 1 0 1 0 1-11 0-22 0-32 0-1 0-3 0-4 0 0 0 0-4 0-4 0-5 0-11 0-16 0 0 1 0 1 0 1 0 3 0 4 0 3 0 5 0 8 0 0 0 0-5 0-6 0-11 0-23 0-34 0-11 0-22 0-33 0-1 0-2 0-3 0-1 0-1-1-1-3 0-6 0-9 0-1 0-2 0-3 0 0 0 0-1 0-1 0-6 0-11 0-17 0-1 0-1 0-2 0 0 0 0 0 0 2 0 3 0 4 0 12 0 24 0 36 0 0 0 9 0 9 0 0 5 0 10 0 15 0 1 0 3 0 5 0 0-6 0-7 0 0 0-6 0-6 0 0 1 0 3 0 4 0 6 0 12 0 18 0 3 0 5 0 7 0 1 0 1 0 2 0 0 1 1 2 2 1 1 2 2 3 2 1 1 1 1 2 1 1 0 1 0 1 1 2 1 3 1 4 1 3 1 5 0 7-1 1-1 2-2 3-3 1-1 2-2 2-3 1-2 1-4 1-6 0-3 0-7 0-11 0-11 0-22 0-33 0-1 0-2 1-2 1 0 3 0 5 0 6 0 12 0 19 0 3 0 7 0 11 0 0 0 0 14 0 15 0 2 0 4 0 6-2-1-5-2-7-2z m7 122c-2 0-5 0-7 0-1 0-2 0-3 0 0 0 0 0 0 0-3-5-7-10-10-14-1-2-3-5-4-7 0 0-1-1-1-2 0 0 0-1 0-1 0-1 0-4 0-4 0 0 1 0 2 0 3 0 5 0 8 0 3 0 5 0 8 0 0 0 0-1 0-1 0-1 0-3 0-4 0-2 0-3 0-4 0-1 0-1 1-1 1 0 3 0 4 0 1 0 2 0 2 0 0 3 0 6 0 8 0 1 0 2 1 2 1 0 2 0 4 0 0 0 0 0 0 0 0 1 0 1 0 2 0 0 0 3 0 3-1 0-2 0-3 0-1 0-2 0-2 1 0 7 0 15 0 22z m-7-15c0-1 0-2 0-4 0-1 0-1 0-2 0 0 0-1 0-2 0 0-1 0-1 0-1 0-2 0-3 0-1 0-3 0-4 0 1 2 3 4 4 6 1 1 1 2 2 3 1 2 2 4 2 7 0-3 0-5 0-8z m41-2c-3 2-8 2-11 2-1 0-2 0-2 0 0 0 0 1 0 1 0 2 0 3 0 4 0 0 13 0 14 0 1 0 1 0 1 1 0 1 0 2 0 4 0 1 0 2 0 3 0 0-1 0-1 0-6 0-11 0-17 0-1 0-1 0-2 0 0 0 0-1 0-1-1-2-1-4-1-6-1-5-1-9-2-14 4 0 9 1 12-1 3-1 4-4 4-7-1-4-5-4-7-4-2 0-9-1-9 2-1-2-1-5-2-8 1 0 3-1 5-1 2-1 5-1 7-1 4 0 8 2 11 5 2 3 2 7 2 11 0 2 0 5 0 7 0 1-1 2-2 3 0 0 0 0 0 0-3 2 2 0 0 0z" horiz-adv-x="1000" />
90
92
91 <glyph glyph-name="up" unicode="&#xe832;" d="M687 254l-173 217c-8 9-22 9-29 0l-173-217c-9-12-1-29 15-29h345c16 0 24 17 15 29z" horiz-adv-x="1000" />
93 <glyph glyph-name="up" unicode="&#xe832;" d="M687 254l-173 217c-8 9-22 9-29 0l-173-217c-9-12-1-29 15-29h345c16 0 24 17 15 29z" horiz-adv-x="1000" />
92
94
93 <glyph glyph-name="merge" unicode="&#xe833;" d="M200 110c0-72 58-131 130-131s130 59 130 131c0 45-24 86-60 109 18 139 133 179 202 190v-301c-38-23-65-64-65-112 0-72 59-130 130-130s130 58 130 130c0 48-26 89-65 112v487c39 23 65 64 65 112 0 72-58 130-130 130s-130-58-130-130c0-48 27-89 65-112v-55c-60-8-162-32-238-108-54-54-86-124-94-208-42-22-70-65-70-114z m468-158c-24 0-44 20-44 43s20 44 44 44c24 0 43-20 43-44s-19-43-43-43z m0 798c24 0 43-19 43-43s-20-43-43-43c-24 0-44 19-44 43s20 43 44 43z m-338-684c-24 0-43 20-43 43s19 44 43 44c24 0 43-20 43-44s-19-43-43-43z" horiz-adv-x="1000" />
95 <glyph glyph-name="merge" unicode="&#xe833;" d="M200 110c0-72 58-131 130-131s130 59 130 131c0 45-24 86-60 109 18 139 133 179 202 190v-301c-38-23-65-64-65-112 0-72 59-130 130-130s130 58 130 130c0 48-26 89-65 112v487c39 23 65 64 65 112 0 72-58 130-130 130s-130-58-130-130c0-48 27-89 65-112v-55c-60-8-162-32-238-108-54-54-86-124-94-208-42-22-70-65-70-114z m468-158c-24 0-44 20-44 43s20 44 44 44c24 0 43-20 43-44s-19-43-43-43z m0 798c24 0 43-19 43-43s-20-43-43-43c-24 0-44 19-44 43s20 43 44 43z m-338-684c-24 0-43 20-43 43s19 44 43 44c24 0 43-20 43-44s-19-43-43-43z" horiz-adv-x="1000" />
94
96
95 <glyph glyph-name="spin-alt" unicode="&#xe834;" d="M498 850c-114 0-228-39-320-116l0 0c173 140 428 130 588-31 134-134 164-332 89-495-10-29-5-50 12-68 21-20 61-23 84 0 3 3 12 15 15 24 71 180 33 393-112 539-99 98-228 147-356 147z m-409-274c-14 0-29-5-39-16-3-3-13-15-15-24-71-180-34-393 112-539 185-185 479-195 676-31l0 0c-173-140-428-130-589 31-134 134-163 333-89 495 11 29 6 50-12 68-11 11-27 17-44 16z" horiz-adv-x="1001" />
97 <glyph glyph-name="spin-alt" unicode="&#xe834;" d="M498 850c-114 0-228-39-320-116l0 0c173 140 428 130 588-31 134-134 164-332 89-495-10-29-5-50 12-68 21-20 61-23 84 0 3 3 12 15 15 24 71 180 33 393-112 539-99 98-228 147-356 147z m-409-274c-14 0-29-5-39-16-3-3-13-15-15-24-71-180-34-393 112-539 185-185 479-195 676-31l0 0c-173-140-428-130-589 31-134 134-163 333-89 495 11 29 6 50-12 68-11 11-27 17-44 16z" horiz-adv-x="1001" />
96
98
97 <glyph glyph-name="spin" unicode="&#xe838;" d="M462 850c-6 0-11-5-11-11l0-183 0 0c0-6 5-11 11-11l69 0c1 0 1 0 1 0 7 0 12 5 12 11l0 183 0 0c0 6-5 11-12 11l-69 0c0 0 0 0-1 0z m250-47c-4 1-8-2-10-5l-91-158 0 0c-4-6-2-13 4-16l60-34c0-1 0-1 0-1 6-3 13-1 16 4l91 158c3 6 2 13-4 16l-61 35c-1 1-3 1-5 1z m-428-2c-2 0-4-1-6-2l-61-35c-5-3-7-10-4-16l91-157c0 0 0 0 0 0 3-6 10-8 16-5l61 35c5 4 7 11 4 16l-91 157c0 1 0 1 0 1-2 4-6 6-10 6z m620-163c-2 0-4 0-6-1l-157-91c0 0 0 0 0 0-6-3-8-10-5-16l35-61c4-5 11-7 16-4l157 91c1 0 1 0 1 0 6 3 7 11 4 16l-35 61c-2 4-6 6-10 5z m-810-4c-5 0-9-2-11-6l-35-61c-3-5-1-12 4-15l158-91 0 0c6-4 13-2 16 4l35 60c0 0 0 0 0 0 3 6 1 13-4 16l-158 91c-2 1-4 2-5 2z m712-235l0 0c-6 0-11-5-11-11l0-69c0-1 0-1 0-1 0-7 5-12 11-12l183 0 0 0c6 0 11 5 11 12l0 69c0 0 0 0 0 1 0 6-5 11-11 11l-183 0z m-794-5l0 0c-7 0-12-5-12-12l0-69c0 0 0 0 0-1 0-6 5-11 12-11l182 0 0 0c6 0 11 5 11 11l0 69c0 1 0 1 0 1 0 7-5 12-11 12l-182 0z m772-153c-4 0-8-2-10-6l-34-60c-1 0-1 0-1 0-3-6-1-13 4-16l158-91c6-3 13-1 16 4l35 61c3 5 1 12-4 15l-158 92 0 0c-2 1-4 1-6 1z m-566-5c-1 0-3 0-5-1l-157-91c0 0-1 0-1 0-5-3-7-10-4-16l35-61c3-5 10-7 16-4l157 91c0 0 0 0 0 0 6 3 8 10 5 16l-35 61c-3 3-7 6-11 5z m468-121c-2 0-4 0-6-1l-61-35c-5-4-7-11-4-16l91-157c0-1 0-1 0-1 3-6 11-7 16-4l61 35c5 3 7 10 4 16l-91 157c0 0 0 0 0 0-2 4-6 6-10 6z m-367-2c-4 0-8-2-10-6l-91-158c-3-6-1-13 4-16l61-35c5-3 12-1 15 4l92 158 0 0c3 6 1 13-5 16l-60 35c0 0 0 0 0 0-2 1-4 1-6 2z m149-58c-7 0-12-5-12-11l0-183 0 0c0-6 5-11 12-11l69 0c0 0 0 0 1 0 6 0 11 5 11 11l0 183 0 0c0 6-5 11-11 11l-69 0c-1 0-1 0-1 0z" horiz-adv-x="1000" />
99 <glyph glyph-name="spin" unicode="&#xe838;" d="M462 850c-6 0-11-5-11-11l0-183 0 0c0-6 5-11 11-11l69 0c1 0 1 0 1 0 7 0 12 5 12 11l0 183 0 0c0 6-5 11-12 11l-69 0c0 0 0 0-1 0z m250-47c-4 1-8-2-10-5l-91-158 0 0c-4-6-2-13 4-16l60-34c0-1 0-1 0-1 6-3 13-1 16 4l91 158c3 6 2 13-4 16l-61 35c-1 1-3 1-5 1z m-428-2c-2 0-4-1-6-2l-61-35c-5-3-7-10-4-16l91-157c0 0 0 0 0 0 3-6 10-8 16-5l61 35c5 4 7 11 4 16l-91 157c0 1 0 1 0 1-2 4-6 6-10 6z m620-163c-2 0-4 0-6-1l-157-91c0 0 0 0 0 0-6-3-8-10-5-16l35-61c4-5 11-7 16-4l157 91c1 0 1 0 1 0 6 3 7 11 4 16l-35 61c-2 4-6 6-10 5z m-810-4c-5 0-9-2-11-6l-35-61c-3-5-1-12 4-15l158-91 0 0c6-4 13-2 16 4l35 60c0 0 0 0 0 0 3 6 1 13-4 16l-158 91c-2 1-4 2-5 2z m712-235l0 0c-6 0-11-5-11-11l0-69c0-1 0-1 0-1 0-7 5-12 11-12l183 0 0 0c6 0 11 5 11 12l0 69c0 0 0 0 0 1 0 6-5 11-11 11l-183 0z m-794-5l0 0c-7 0-12-5-12-12l0-69c0 0 0 0 0-1 0-6 5-11 12-11l182 0 0 0c6 0 11 5 11 11l0 69c0 1 0 1 0 1 0 7-5 12-11 12l-182 0z m772-153c-4 0-8-2-10-6l-34-60c-1 0-1 0-1 0-3-6-1-13 4-16l158-91c6-3 13-1 16 4l35 61c3 5 1 12-4 15l-158 92 0 0c-2 1-4 1-6 1z m-566-5c-1 0-3 0-5-1l-157-91c0 0-1 0-1 0-5-3-7-10-4-16l35-61c3-5 10-7 16-4l157 91c0 0 0 0 0 0 6 3 8 10 5 16l-35 61c-3 3-7 6-11 5z m468-121c-2 0-4 0-6-1l-61-35c-5-4-7-11-4-16l91-157c0-1 0-1 0-1 3-6 11-7 16-4l61 35c5 3 7 10 4 16l-91 157c0 0 0 0 0 0-2 4-6 6-10 6z m-367-2c-4 0-8-2-10-6l-91-158c-3-6-1-13 4-16l61-35c5-3 12-1 15 4l92 158 0 0c3 6 1 13-5 16l-60 35c0 0 0 0 0 0-2 1-4 1-6 2z m149-58c-7 0-12-5-12-11l0-183 0 0c0-6 5-11 12-11l69 0c0 0 0 0 1 0 6 0 11 5 11 11l0 183 0 0c0 6-5 11-11 11l-69 0c-1 0-1 0-1 0z" horiz-adv-x="1000" />
98
100
99 <glyph glyph-name="docs" unicode="&#xf0c5;" d="M946 636q23 0 38-16t16-38v-678q0-23-16-38t-38-16h-535q-23 0-38 16t-16 38v160h-303q-23 0-38 16t-16 38v375q0 22 11 49t27 42l228 228q15 16 42 27t49 11h232q23 0 38-16t16-38v-183q38 23 71 23h232z m-303-119l-167-167h167v167z m-357 214l-167-167h167v167z m109-361l176 176v233h-214v-233q0-22-15-37t-38-16h-233v-357h286v143q0 22 11 49t27 42z m534-449v643h-215v-232q0-22-15-38t-38-15h-232v-358h500z" horiz-adv-x="1000" />
101 <glyph glyph-name="docs" unicode="&#xf0c5;" d="M946 636q23 0 38-16t16-38v-678q0-23-16-38t-38-16h-535q-23 0-38 16t-16 38v160h-303q-23 0-38 16t-16 38v375q0 22 11 49t27 42l228 228q15 16 42 27t49 11h232q23 0 38-16t16-38v-183q38 23 71 23h232z m-303-119l-167-167h167v167z m-357 214l-167-167h167v167z m109-361l176 176v233h-214v-233q0-22-15-37t-38-16h-233v-357h286v143q0 22 11 49t27 42z m534-449v643h-215v-232q0-22-15-38t-38-15h-232v-358h500z" horiz-adv-x="1000" />
100
102
101 <glyph glyph-name="menu" unicode="&#xf0c9;" d="M857 100v-71q0-15-10-25t-26-11h-785q-15 0-25 11t-11 25v71q0 15 11 25t25 11h785q15 0 26-11t10-25z m0 286v-72q0-14-10-25t-26-10h-785q-15 0-25 10t-11 25v72q0 14 11 25t25 10h785q15 0 26-10t10-25z m0 285v-71q0-14-10-25t-26-11h-785q-15 0-25 11t-11 25v71q0 15 11 26t25 10h785q15 0 26-10t10-26z" horiz-adv-x="857.1" />
103 <glyph glyph-name="menu" unicode="&#xf0c9;" d="M857 100v-71q0-15-10-25t-26-11h-785q-15 0-25 11t-11 25v71q0 15 11 25t25 11h785q15 0 26-11t10-25z m0 286v-72q0-14-10-25t-26-10h-785q-15 0-25 10t-11 25v72q0 14 11 25t25 10h785q15 0 26-10t10-25z m0 285v-71q0-14-10-25t-26-11h-785q-15 0-25 11t-11 25v71q0 15 11 26t25 10h785q15 0 26-10t10-26z" horiz-adv-x="857.1" />
102
104
103 <glyph glyph-name="paste" unicode="&#xf0ea;" d="M429-79h500v358h-233q-22 0-37 15t-16 38v232h-214v-643z m142 804v36q0 7-5 12t-12 6h-393q-7 0-13-6t-5-12v-36q0-7 5-13t13-5h393q7 0 12 5t5 13z m143-375h167l-167 167v-167z m286-71v-375q0-23-16-38t-38-16h-535q-23 0-38 16t-16 38v89h-303q-23 0-38 16t-16 37v750q0 23 16 38t38 16h607q22 0 38-16t15-38v-183q12-7 20-15l228-228q16-15 27-42t11-49z" horiz-adv-x="1000" />
105 <glyph glyph-name="paste" unicode="&#xf0ea;" d="M429-79h500v358h-233q-22 0-37 15t-16 38v232h-214v-643z m142 804v36q0 7-5 12t-12 6h-393q-7 0-13-6t-5-12v-36q0-7 5-13t13-5h393q7 0 12 5t5 13z m143-375h167l-167 167v-167z m286-71v-375q0-23-16-38t-38-16h-535q-23 0-38 16t-16 38v89h-303q-23 0-38 16t-16 37v750q0 23 16 38t38 16h607q22 0 38-16t15-38v-183q12-7 20-15l228-228q16-15 27-42t11-49z" horiz-adv-x="1000" />
104
106
105 <glyph glyph-name="doc-text" unicode="&#xf0f6;" d="M819 638q16-16 27-42t11-50v-642q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h500q22 0 49-11t42-27z m-248 136v-210h210q-5 17-12 23l-175 175q-6 7-23 12z m215-853v572h-232q-23 0-38 16t-16 37v233h-429v-858h715z m-572 483q0 7 5 12t13 5h393q8 0 13-5t5-12v-36q0-8-5-13t-13-5h-393q-8 0-13 5t-5 13v36z m411-125q8 0 13-5t5-13v-36q0-8-5-13t-13-5h-393q-8 0-13 5t-5 13v36q0 8 5 13t13 5h393z m0-143q8 0 13-5t5-13v-36q0-8-5-13t-13-5h-393q-8 0-13 5t-5 13v36q0 8 5 13t13 5h393z" horiz-adv-x="857.1" />
107 <glyph glyph-name="doc-text" unicode="&#xf0f6;" d="M819 638q16-16 27-42t11-50v-642q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h500q22 0 49-11t42-27z m-248 136v-210h210q-5 17-12 23l-175 175q-6 7-23 12z m215-853v572h-232q-23 0-38 16t-16 37v233h-429v-858h715z m-572 483q0 7 5 12t13 5h393q8 0 13-5t5-12v-36q0-8-5-13t-13-5h-393q-8 0-13 5t-5 13v36z m411-125q8 0 13-5t5-13v-36q0-8-5-13t-13-5h-393q-8 0-13 5t-5 13v36q0 8 5 13t13 5h393z m0-143q8 0 13-5t5-13v-36q0-8-5-13t-13-5h-393q-8 0-13 5t-5 13v36q0 8 5 13t13 5h393z" horiz-adv-x="857.1" />
106
108
107 <glyph glyph-name="plus-squared" unicode="&#xf0fe;" d="M714 314v72q0 14-10 25t-25 10h-179v179q0 15-11 25t-25 11h-71q-15 0-25-11t-11-25v-179h-178q-15 0-25-10t-11-25v-72q0-14 11-25t25-10h178v-179q0-14 11-25t25-11h71q15 0 25 11t11 25v179h179q14 0 25 10t10 25z m143 304v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
109 <glyph glyph-name="plus-squared" unicode="&#xf0fe;" d="M714 314v72q0 14-10 25t-25 10h-179v179q0 15-11 25t-25 11h-71q-15 0-25-11t-11-25v-179h-178q-15 0-25-10t-11-25v-72q0-14 11-25t25-10h178v-179q0-14 11-25t25-11h71q15 0 25 11t11 25v179h179q14 0 25 10t10 25z m143 304v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
108
110
109 <glyph glyph-name="folder-empty" unicode="&#xf114;" d="M857 118v393q0 22-15 38t-38 15h-393q-23 0-38 16t-16 38v36q0 22-15 38t-38 15h-179q-22 0-38-15t-16-38v-536q0-22 16-38t38-16h679q22 0 38 16t15 38z m72 393v-393q0-51-37-88t-88-37h-679q-51 0-88 37t-37 88v536q0 51 37 88t88 37h179q51 0 88-37t37-88v-18h375q51 0 88-37t37-88z" horiz-adv-x="928.6" />
111 <glyph glyph-name="folder-empty" unicode="&#xf114;" d="M857 118v393q0 22-15 38t-38 15h-393q-23 0-38 16t-16 38v36q0 22-15 38t-38 15h-179q-22 0-38-15t-16-38v-536q0-22 16-38t38-16h679q22 0 38 16t15 38z m72 393v-393q0-51-37-88t-88-37h-679q-51 0-88 37t-37 88v536q0 51 37 88t88 37h179q51 0 88-37t37-88v-18h375q51 0 88-37t37-88z" horiz-adv-x="928.6" />
110
112
111 <glyph glyph-name="folder-open-empty" unicode="&#xf115;" d="M994 331q0 19-30 19h-607q-22 0-48-12t-39-29l-164-203q-11-13-11-22 0-20 30-20h607q23 0 48 13t40 29l164 203q10 12 10 22z m-637 90h429v90q0 22-16 38t-38 15h-321q-23 0-38 16t-16 38v36q0 22-15 38t-38 15h-179q-22 0-38-15t-16-38v-476l143 175q25 30 65 49t78 19z m708-90q0-35-25-67l-165-203q-24-30-65-49t-78-19h-607q-51 0-88 37t-37 88v536q0 51 37 88t88 37h179q51 0 88-37t37-88v-18h303q52 0 88-37t37-88v-90h107q30 0 56-13t37-40q8-17 8-37z" horiz-adv-x="1071.4" />
113 <glyph glyph-name="folder-open-empty" unicode="&#xf115;" d="M994 331q0 19-30 19h-607q-22 0-48-12t-39-29l-164-203q-11-13-11-22 0-20 30-20h607q23 0 48 13t40 29l164 203q10 12 10 22z m-637 90h429v90q0 22-16 38t-38 15h-321q-23 0-38 16t-16 38v36q0 22-15 38t-38 15h-179q-22 0-38-15t-16-38v-476l143 175q25 30 65 49t78 19z m708-90q0-35-25-67l-165-203q-24-30-65-49t-78-19h-607q-51 0-88 37t-37 88v536q0 51 37 88t88 37h179q51 0 88-37t37-88v-18h303q52 0 88-37t37-88v-90h107q30 0 56-13t37-40q8-17 8-37z" horiz-adv-x="1071.4" />
112
114
113 <glyph glyph-name="minus-squared" unicode="&#xf146;" d="M714 314v72q0 14-10 25t-25 10h-500q-15 0-25-10t-11-25v-72q0-14 11-25t25-10h500q14 0 25 10t10 25z m143 304v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
115 <glyph glyph-name="minus-squared" unicode="&#xf146;" d="M714 314v72q0 14-10 25t-25 10h-500q-15 0-25-10t-11-25v-72q0-14 11-25t25-10h500q14 0 25 10t10 25z m143 304v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
114
116
115 <glyph glyph-name="minus-squared-alt" unicode="&#xf147;" d="M643 404v-36q0-8-5-13t-13-5h-464q-8 0-13 5t-5 13v36q0 7 5 12t13 5h464q8 0 13-5t5-12z m71-250v464q0 37-26 63t-63 26h-464q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63z m72 464v-464q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h464q66 0 114-48t47-113z" horiz-adv-x="785.7" />
117 <glyph glyph-name="minus-squared-alt" unicode="&#xf147;" d="M643 404v-36q0-8-5-13t-13-5h-464q-8 0-13 5t-5 13v36q0 7 5 12t13 5h464q8 0 13-5t5-12z m71-250v464q0 37-26 63t-63 26h-464q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63z m72 464v-464q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h464q66 0 114-48t47-113z" horiz-adv-x="785.7" />
116
118
117 <glyph glyph-name="doc-inv" unicode="&#xf15b;" d="M571 564v264q13-8 21-16l227-228q8-7 16-20h-264z m-71-18q0-22 16-37t38-16h303v-589q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h446v-304z" horiz-adv-x="857.1" />
119 <glyph glyph-name="doc-inv" unicode="&#xf15b;" d="M571 564v264q13-8 21-16l227-228q8-7 16-20h-264z m-71-18q0-22 16-37t38-16h303v-589q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h446v-304z" horiz-adv-x="857.1" />
118
120
119 <glyph glyph-name="doc-text-inv" unicode="&#xf15c;" d="M819 584q8-7 16-20h-264v264q13-8 21-16z m-265-91h303v-589q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h446v-304q0-22 16-37t38-16z m89-411v36q0 8-5 13t-13 5h-393q-8 0-13-5t-5-13v-36q0-8 5-13t13-5h393q8 0 13 5t5 13z m0 143v36q0 8-5 13t-13 5h-393q-8 0-13-5t-5-13v-36q0-8 5-13t13-5h393q8 0 13 5t5 13z m0 143v36q0 7-5 12t-13 5h-393q-8 0-13-5t-5-12v-36q0-8 5-13t13-5h393q8 0 13 5t5 13z" horiz-adv-x="857.1" />
121 <glyph glyph-name="doc-text-inv" unicode="&#xf15c;" d="M819 584q8-7 16-20h-264v264q13-8 21-16z m-265-91h303v-589q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h446v-304q0-22 16-37t38-16z m89-411v36q0 8-5 13t-13 5h-393q-8 0-13-5t-5-13v-36q0-8 5-13t13-5h393q8 0 13 5t5 13z m0 143v36q0 8-5 13t-13 5h-393q-8 0-13-5t-5-13v-36q0-8 5-13t13-5h393q8 0 13 5t5 13z m0 143v36q0 7-5 12t-13 5h-393q-8 0-13-5t-5-12v-36q0-8 5-13t13-5h393q8 0 13 5t5 13z" horiz-adv-x="857.1" />
120
122
121 <glyph glyph-name="plus-squared-alt" unicode="&#xf196;" d="M643 404v-36q0-8-5-13t-13-5h-196v-196q0-8-5-13t-13-5h-36q-8 0-13 5t-5 13v196h-196q-8 0-13 5t-5 13v36q0 7 5 12t13 5h196v197q0 8 5 13t13 5h36q8 0 13-5t5-13v-197h196q8 0 13-5t5-12z m71-250v464q0 37-26 63t-63 26h-464q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63z m72 464v-464q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h464q66 0 114-48t47-113z" horiz-adv-x="785.7" />
123 <glyph glyph-name="plus-squared-alt" unicode="&#xf196;" d="M643 404v-36q0-8-5-13t-13-5h-196v-196q0-8-5-13t-13-5h-36q-8 0-13 5t-5 13v196h-196q-8 0-13 5t-5 13v36q0 7 5 12t13 5h196v197q0 8 5 13t13 5h36q8 0 13-5t5-13v-197h196q8 0 13-5t5-12z m71-250v464q0 37-26 63t-63 26h-464q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63z m72 464v-464q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h464q66 0 114-48t47-113z" horiz-adv-x="785.7" />
122
124
123 <glyph glyph-name="file-code" unicode="&#xf1c9;" d="M819 638q16-16 27-42t11-50v-642q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h500q22 0 49-11t42-27z m-248 136v-210h210q-5 17-12 23l-175 175q-6 7-23 12z m215-853v572h-232q-23 0-38 16t-16 37v233h-429v-858h715z m-518 500q4 7 12 7t13-3l28-21q7-5 7-12t-3-13l-102-136 102-136q4-6 3-13t-7-12l-28-21q-6-4-13-4t-12 7l-126 168q-8 11 0 22z m447-167q8-11 0-22l-126-168q-4-6-11-7t-14 4l-28 21q-6 5-7 12t3 13l102 136-102 136q-4 6-3 13t7 12l28 21q6 4 14 3t11-7z m-346-258q-7 1-11 8t-3 13l77 464q1 7 7 11t14 3l35-5q7-2 11-8t3-13l-77-464q-1-7-7-11t-13-3z" horiz-adv-x="857.1" />
125 <glyph glyph-name="file-code" unicode="&#xf1c9;" d="M819 638q16-16 27-42t11-50v-642q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h500q22 0 49-11t42-27z m-248 136v-210h210q-5 17-12 23l-175 175q-6 7-23 12z m215-853v572h-232q-23 0-38 16t-16 37v233h-429v-858h715z m-518 500q4 7 12 7t13-3l28-21q7-5 7-12t-3-13l-102-136 102-136q4-6 3-13t-7-12l-28-21q-6-4-13-4t-12 7l-126 168q-8 11 0 22z m447-167q8-11 0-22l-126-168q-4-6-11-7t-14 4l-28 21q-6 5-7 12t3 13l102 136-102 136q-4 6-3 13t7 12l28 21q6 4 14 3t11-7z m-346-258q-7 1-11 8t-3 13l77 464q1 7 7 11t14 3l35-5q7-2 11-8t3-13l-77-464q-1-7-7-11t-13-3z" horiz-adv-x="857.1" />
124
126
125 <glyph glyph-name="sliders" unicode="&#xf1de;" d="M196 64v-71h-196v71h196z m197 72q14 0 25-11t11-25v-143q0-14-11-25t-25-11h-143q-14 0-25 11t-11 25v143q0 15 11 25t25 11h143z m89 214v-71h-482v71h482z m-357 286v-72h-125v72h125z m732-572v-71h-411v71h411z m-536 643q15 0 26-10t10-26v-142q0-15-10-25t-26-11h-142q-15 0-25 11t-11 25v142q0 15 11 26t25 10h142z m358-286q14 0 25-10t10-25v-143q0-15-10-25t-25-11h-143q-15 0-25 11t-11 25v143q0 14 11 25t25 10h143z m178-71v-71h-125v71h125z m0 286v-72h-482v72h482z" horiz-adv-x="857.1" />
127 <glyph glyph-name="sliders" unicode="&#xf1de;" d="M196 64v-71h-196v71h196z m197 72q14 0 25-11t11-25v-143q0-14-11-25t-25-11h-143q-14 0-25 11t-11 25v143q0 15 11 25t25 11h143z m89 214v-71h-482v71h482z m-357 286v-72h-125v72h125z m732-572v-71h-411v71h411z m-536 643q15 0 26-10t10-26v-142q0-15-10-25t-26-11h-142q-15 0-25 11t-11 25v142q0 15 11 26t25 10h142z m358-286q14 0 25-10t10-25v-143q0-15-10-25t-25-11h-143q-15 0-25 11t-11 25v143q0 14 11 25t25 10h143z m178-71v-71h-125v71h125z m0 286v-72h-482v72h482z" horiz-adv-x="857.1" />
126
128
127 <glyph glyph-name="trash" unicode="&#xf1f8;" d="M286 82v393q0 8-5 13t-13 5h-36q-8 0-13-5t-5-13v-393q0-8 5-13t13-5h36q8 0 13 5t5 13z m143 0v393q0 8-5 13t-13 5h-36q-8 0-13-5t-5-13v-393q0-8 5-13t13-5h36q8 0 13 5t5 13z m142 0v393q0 8-5 13t-12 5h-36q-8 0-13-5t-5-13v-393q0-8 5-13t13-5h36q7 0 12 5t5 13z m-303 554h250l-27 65q-4 5-9 6h-177q-6-1-10-6z m518-18v-36q0-8-5-13t-13-5h-54v-529q0-46-26-80t-63-34h-464q-37 0-63 33t-27 79v531h-53q-8 0-13 5t-5 13v36q0 8 5 13t13 5h172l39 93q9 21 31 35t44 15h178q23 0 44-15t30-35l39-93h173q8 0 13-5t5-13z" horiz-adv-x="785.7" />
129 <glyph glyph-name="trash" unicode="&#xf1f8;" d="M286 82v393q0 8-5 13t-13 5h-36q-8 0-13-5t-5-13v-393q0-8 5-13t13-5h36q8 0 13 5t5 13z m143 0v393q0 8-5 13t-13 5h-36q-8 0-13-5t-5-13v-393q0-8 5-13t13-5h36q8 0 13 5t5 13z m142 0v393q0 8-5 13t-12 5h-36q-8 0-13-5t-5-13v-393q0-8 5-13t13-5h36q7 0 12 5t5 13z m-303 554h250l-27 65q-4 5-9 6h-177q-6-1-10-6z m518-18v-36q0-8-5-13t-13-5h-54v-529q0-46-26-80t-63-34h-464q-37 0-63 33t-27 79v531h-53q-8 0-13 5t-5 13v36q0 8 5 13t13 5h172l39 93q9 21 31 35t44 15h178q23 0 44-15t30-35l39-93h173q8 0 13-5t5-13z" horiz-adv-x="785.7" />
128 </font>
130 </font>
129 </defs>
131 </defs>
130 </svg> No newline at end of file
132 </svg>
1 NO CONTENT: modified file, binary diff hidden
NO CONTENT: modified file, binary diff hidden
1 NO CONTENT: modified file, binary diff hidden
NO CONTENT: modified file, binary diff hidden
1 NO CONTENT: modified file, binary diff hidden
NO CONTENT: modified file, binary diff hidden
@@ -1,82 +1,75 b''
1 /* COMMON */
1 /* COMMON */
2 var select2RefFilterResults = function(queryTerm, data) {
2 var select2RefFilterResults = function(queryTerm, data) {
3 var filteredData = {results: []};
3 var filteredData = {results: []};
4 //filter results
4 //filter results
5 $.each(data.results, function() {
5 $.each(data.results, function() {
6 var section = this.text;
6 var section = this.text;
7 var children = [];
7 var children = [];
8 $.each(this.children, function() {
8 $.each(this.children, function() {
9 if (queryTerm.length === 0 || this.text.toUpperCase().indexOf(queryTerm.toUpperCase()) >= 0) {
9 if (queryTerm.length === 0 || this.text.toUpperCase().indexOf(queryTerm.toUpperCase()) >= 0) {
10 children.push(this);
10 children.push(this);
11 }
11 }
12 });
12 });
13
13
14 if (children.length > 0) {
14 if (children.length > 0) {
15 filteredData.results.push({
15 filteredData.results.push({
16 'text': section,
16 'text': section,
17 'children': children
17 'children': children
18 });
18 });
19 }
19 }
20 });
20 });
21
21
22 return filteredData
22 return filteredData
23 };
23 };
24
24
25
25
26 var select2RefBaseSwitcher = function(targetElement, loadUrl, initialData){
26 var select2RefBaseSwitcher = function(targetElement, loadUrl, initialData){
27 var formatResult = function(result, container, query) {
27 var formatResult = function(result, container, query) {
28 return formatSelect2SelectionRefs(result);
28 return formatSelect2SelectionRefs(result);
29 };
29 };
30
30
31 var formatSelection = function(data, container) {
31 var formatSelection = function(data, container) {
32 return formatSelect2SelectionRefs(data);
32 return formatSelect2SelectionRefs(data);
33 };
33 };
34
34
35 $(targetElement).select2({
35 $(targetElement).select2({
36 cachedDataSource: {},
36 cachedDataSource: {},
37 dropdownAutoWidth: true,
37 dropdownAutoWidth: true,
38 width: "resolve",
38 width: "resolve",
39 containerCssClass: "drop-menu",
39 containerCssClass: "drop-menu",
40 dropdownCssClass: "drop-menu-dropdown",
40 dropdownCssClass: "drop-menu-dropdown",
41 query: function(query) {
41 query: function(query) {
42 var self = this;
42 var self = this;
43 var cacheKey = '__ALLREFS__';
43 var cacheKey = '__ALLREFS__';
44 var cachedData = self.cachedDataSource[cacheKey];
44 var cachedData = self.cachedDataSource[cacheKey];
45 if (cachedData) {
45 if (cachedData) {
46 var data = select2RefFilterResults(query.term, cachedData);
46 var data = select2RefFilterResults(query.term, cachedData);
47 query.callback({results: data.results});
47 query.callback({results: data.results});
48 } else {
48 } else {
49 $.ajax({
49 $.ajax({
50 url: loadUrl,
50 url: loadUrl,
51 data: {},
51 data: {},
52 dataType: 'json',
52 dataType: 'json',
53 type: 'GET',
53 type: 'GET',
54 success: function(data) {
54 success: function(data) {
55 self.cachedDataSource[cacheKey] = data;
55 self.cachedDataSource[cacheKey] = data;
56 query.callback({results: data.results});
56 query.callback({results: data.results});
57 }
57 }
58 });
58 });
59 }
59 }
60 },
60 },
61 initSelection: function(element, callback) {
61 initSelection: function(element, callback) {
62 callback(initialData);
62 callback(initialData);
63 },
63 },
64 formatResult: formatResult,
64 formatResult: formatResult,
65 formatSelection: formatSelection
65 formatSelection: formatSelection
66 });
66 });
67
67
68 };
68 };
69
69
70 /* WIDGETS */
70 /* WIDGETS */
71 var select2RefSwitcher = function(targetElement, initialData) {
71 var select2RefSwitcher = function(targetElement, initialData) {
72 var loadUrl = pyroutes.url('repo_refs_data',
72 var loadUrl = pyroutes.url('repo_refs_data',
73 {'repo_name': templateContext.repo_name});
73 {'repo_name': templateContext.repo_name});
74 select2RefBaseSwitcher(targetElement, loadUrl, initialData);
74 select2RefBaseSwitcher(targetElement, loadUrl, initialData);
75 };
75 };
76
77 var select2FileHistorySwitcher = function(targetElement, initialData, state) {
78 var loadUrl = pyroutes.url('repo_file_history',
79 {'repo_name': templateContext.repo_name, 'commit_id': state.rev,
80 'f_path': state.f_path});
81 select2RefBaseSwitcher(targetElement, loadUrl, initialData);
82 };
@@ -1,39 +1,51 b''
1 <%namespace name="base" file="/base/base.mako"/>
1 <%namespace name="base" file="/base/base.mako"/>
2 <div class="table">
2 <div class="table">
3
3
4 <table class="table rctable file_history">
4 <table class="table rctable file_history">
5 %for cnt,cs in enumerate(c.pagination):
5 %for cnt,cs in enumerate(c.pagination):
6 <tr id="chg_${cnt+1}" class="${'tablerow%s' % (cnt%2)}">
6 <tr id="chg_${cnt+1}" class="${('tablerow%s' % (cnt%2))}">
7 <td class="td-user">
7 <td class="td-user">
8 ${base.gravatar_with_user(cs.author, 16)}
8 ${base.gravatar_with_user(cs.author, 16)}
9 </td>
9 </td>
10 <td class="td-time">
10 <td class="td-time">
11 <div class="date">
11 <div class="date">
12 ${h.age_component(cs.date)}
12 ${h.age_component(cs.date)}
13 </div>
13 </div>
14 </td>
14 </td>
15 <td class="td-message">
15 <td class="td-message">
16 <div class="log-container">
16 <div class="log-container">
17 <div class="message_history" title="${h.tooltip(cs.message)}">
17 <div class="message_history" title="${h.tooltip(cs.message)}">
18 <a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=cs.raw_id)}">
18 <a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=cs.raw_id)}">
19 ${h.shorter(cs.message, 75)}
19 ${h.shorter(cs.message, 75)}
20 </a>
20 </a>
21 </div>
21 </div>
22 </div>
22 </div>
23 </td>
23 </td>
24 <td class="td-hash">
24 <td class="td-hash">
25 <code>
25 <code>
26 <a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=cs.raw_id)}">
26 <a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=cs.raw_id)}">
27 <span>${h.show_id(cs)}</span>
27 <span>${h.show_id(cs)}</span>
28 </a>
28 </a>
29 </code>
29 </code>
30 </td>
30 </td>
31 <td class="td-actions">
31 <td class="td-actions">
32 <a href="${h.route_path('repo_files',repo_name=c.repo_name,commit_id=cs.raw_id,f_path=c.changelog_for_path)}">
32 <a href="${h.route_path('repo_files',repo_name=c.repo_name,commit_id=cs.raw_id,f_path=c.changelog_for_path)}">
33 ${_('Show File')}
33 ${_('Show File')}
34 </a>
34 </a>
35 </td>
35 </td>
36 <td class="td-actions">
37 <a href="${h.route_path('repo_compare',repo_name=c.repo_name, source_ref_type="rev", source_ref=cs.raw_id,target_ref_type="rev", target_ref=c.commit_id,_query=dict(merge='1',f_path=c.changelog_for_path))}">
38 ${_('Diff File')}
39 </a>
40 </td>
36 </tr>
41 </tr>
37 %endfor
42 %endfor
43 <tr>
44 <td colspan="6">
45 <a id="file_history_overview_full" href="${h.route_path('repo_changelog_file',repo_name=c.repo_name, commit_id=c.commit_id, f_path=c.f_path)}">
46 ${_('Show Full History')}
47 </a>
48 </td>
49 </tr>
38 </table>
50 </table>
39 </div>
51 </div>
@@ -1,40 +1,35 b''
1 <%namespace name="base" file="/base/base.mako"/>
1 <%namespace name="base" file="/base/base.mako"/>
2
2
3 % if c.authors:
3 % if c.authors:
4
4
5 <table class="sidebar-right-content">
5 <table class="sidebar-right-content">
6 % for email, user, commits in sorted(c.authors, key=lambda e: c.file_last_commit.author_email!=e[0]):
6 % for email, user, commits in sorted(c.authors, key=lambda e: c.file_last_commit.author_email!=e[0]):
7 <tr class="file_author tooltip" title="${h.tooltip(h.author_string(email))}">
7 <tr class="file_author tooltip" title="${h.tooltip(h.author_string(email))}">
8
8
9 <td>
9 <td>
10 <span class="user commit-author">${h.link_to_user(user)}</span>
10 <span class="user commit-author">${h.link_to_user(user)}</span>
11 % if c.file_author:
11 % if c.file_author:
12 <span class="commit-date">- ${h.age_component(c.file_last_commit.date)}</span>
12 <span class="commit-date">- ${h.age_component(c.file_last_commit.date)}</span>
13 <a href="#ShowAuthors" id="show_authors" class="action_link"> - ${_('Load All Authors')}</a>
13 % elif c.file_last_commit.author_email==email:
14 % elif c.file_last_commit.author_email==email:
14 <span> (${_('last author')})</span>
15 <span> (${_('last author')})</span>
15 % endif
16 % endif
16 </td>
17 </td>
17
18
18 <td>
19 <td>
19 % if not c.file_author:
20 % if not c.file_author:
20 <code>
21 <code>
21 % if commits == 1:
22 % if commits == 1:
22 ${commits} ${_('Commit')}
23 ${commits} ${_('Commit')}
23 % else:
24 % else:
24 ${commits} ${_('Commits')}
25 ${commits} ${_('Commits')}
25 % endif
26 % endif
26 </code>
27 </code>
27 % endif
28 % endif
28 </td>
29 </td>
29 </tr>
30 </tr>
30 <tr>
31
31 <td colspan="2">
32 % if c.file_author:
33 <a href="#ShowAuthors" id="show_authors" class="action_link">${_('Show Authors')}</a>
34 % endif
35 </td>
36 </tr>
37 % endfor
32 % endfor
38 </table>
33 </table>
39 % endif
34 % endif
40
35
This diff has been collapsed as it changes many lines, (556 lines changed) Show them Hide them
@@ -1,393 +1,463 b''
1 <%inherit file="/base/base.mako"/>
1 <%inherit file="/base/base.mako"/>
2
2
3 <%def name="title(*args)">
3 <%def name="title(*args)">
4 ${_('{} Files').format(c.repo_name)}
4 ${_('{} Files').format(c.repo_name)}
5 %if hasattr(c,'file'):
5 %if hasattr(c,'file'):
6 &middot; ${(h.safe_unicode(c.file.path) or '\\')}
6 &middot; ${(h.safe_unicode(c.file.path) or '\\')}
7 %endif
7 %endif
8
8
9 %if c.rhodecode_name:
9 %if c.rhodecode_name:
10 &middot; ${h.branding(c.rhodecode_name)}
10 &middot; ${h.branding(c.rhodecode_name)}
11 %endif
11 %endif
12 </%def>
12 </%def>
13
13
14 <%def name="breadcrumbs_links()">
14 <%def name="breadcrumbs_links()">
15 ${_('Files')}
15 ${_('Files')}
16 %if c.file:
16 %if c.file:
17 @ ${h.show_id(c.commit)}
17 @ ${h.show_id(c.commit)}
18 %endif
18 %endif
19 </%def>
19 </%def>
20
20
21 <%def name="menu_bar_nav()">
21 <%def name="menu_bar_nav()">
22 ${self.menu_items(active='repositories')}
22 ${self.menu_items(active='repositories')}
23 </%def>
23 </%def>
24
24
25 <%def name="menu_bar_subnav()">
25 <%def name="menu_bar_subnav()">
26 ${self.repo_menu(active='files')}
26 ${self.repo_menu(active='files')}
27 </%def>
27 </%def>
28
28
29 <%def name="main()">
29 <%def name="main()">
30 <div>
30 <div>
31 <div id="files_data">
31 <div id="files_data">
32 <%include file='files_pjax.mako'/>
32 <%include file='files_pjax.mako'/>
33 </div>
33 </div>
34 </div>
34 </div>
35 <script>
35 <script>
36
36
37 var metadataRequest = null;
37 var metadataRequest = null;
38 var fileSourcePage = ${c.file_source_page};
38 var fileSourcePage = ${c.file_source_page};
39 var atRef = '${request.GET.get('at', '')}';
39 var atRef = '${request.GET.get('at', '')}';
40
40
41 var getState = function(context) {
41 var getState = function(context) {
42 var url = $(location).attr('href');
42 var url = $(location).attr('href');
43 var _base_url = '${h.route_path("repo_files",repo_name=c.repo_name,commit_id='',f_path='')}';
43 var _base_url = '${h.route_path("repo_files",repo_name=c.repo_name,commit_id='',f_path='')}';
44 var _annotate_url = '${h.route_path("repo_files:annotated",repo_name=c.repo_name,commit_id='',f_path='')}';
44 var _annotate_url = '${h.route_path("repo_files:annotated",repo_name=c.repo_name,commit_id='',f_path='')}';
45 _base_url = _base_url.replace('//', '/');
45 _base_url = _base_url.replace('//', '/');
46 _annotate_url = _annotate_url.replace('//', '/');
46 _annotate_url = _annotate_url.replace('//', '/');
47
47
48 //extract f_path from url.
48 //extract f_path from url.
49 var parts = url.split(_base_url);
49 var parts = url.split(_base_url);
50 if (parts.length != 2) {
50 if (parts.length != 2) {
51 parts = url.split(_annotate_url);
51 parts = url.split(_annotate_url);
52 if (parts.length != 2) {
52 if (parts.length != 2) {
53 var rev = "tip";
53 var rev = "tip";
54 var f_path = "";
54 var f_path = "";
55 } else {
55 } else {
56 var parts2 = parts[1].split('/');
56 var parts2 = parts[1].split('/');
57 var rev = parts2.shift(); // pop the first element which is the revision
57 var rev = parts2.shift(); // pop the first element which is the revision
58 var f_path = parts2.join('/');
58 var f_path = parts2.join('/');
59 }
59 }
60
60
61 } else {
61 } else {
62 var parts2 = parts[1].split('/');
62 var parts2 = parts[1].split('/');
63 var rev = parts2.shift(); // pop the first element which is the revision
63 var rev = parts2.shift(); // pop the first element which is the revision
64 var f_path = parts2.join('/');
64 var f_path = parts2.join('/');
65 }
65 }
66
66
67 var url_params = {
67 var url_params = {
68 repo_name: templateContext.repo_name,
68 repo_name: templateContext.repo_name,
69 commit_id: rev,
69 commit_id: rev,
70 f_path:'__FPATH__'
70 f_path:'__FPATH__'
71 };
71 };
72 if (atRef !== '') {
72 if (atRef !== '') {
73 url_params['at'] = atRef
73 url_params['at'] = atRef
74 }
74 }
75
75
76 var _url_base = pyroutes.url('repo_files', url_params);
76 var _url_base = pyroutes.url('repo_files', url_params);
77 var _node_list_url = pyroutes.url('repo_files_nodelist',
77 var _node_list_url = pyroutes.url('repo_files_nodelist',
78 {repo_name: templateContext.repo_name,
78 {repo_name: templateContext.repo_name,
79 commit_id: rev, f_path: f_path});
79 commit_id: rev, f_path: f_path});
80
80
81 return {
81 return {
82 url: url,
82 url: url,
83 f_path: f_path,
83 f_path: f_path,
84 rev: rev,
84 rev: rev,
85 commit_id: "${c.commit.raw_id}",
85 commit_id: "${c.commit.raw_id}",
86 node_list_url: _node_list_url,
86 node_list_url: _node_list_url,
87 url_base: _url_base
87 url_base: _url_base
88 };
88 };
89 };
89 };
90
90
91 var getFilesMetadata = function() {
91 var getFilesMetadata = function() {
92 if (metadataRequest && metadataRequest.readyState != 4) {
92 if (metadataRequest && metadataRequest.readyState != 4) {
93 metadataRequest.abort();
93 metadataRequest.abort();
94 }
94 }
95 if (fileSourcePage) {
95 if (fileSourcePage) {
96 return false;
96 return false;
97 }
97 }
98
98
99 if ($('#file-tree-wrapper').hasClass('full-load')) {
99 if ($('#file-tree-wrapper').hasClass('full-load')) {
100 // in case our HTML wrapper has full-load class we don't
100 // in case our HTML wrapper has full-load class we don't
101 // trigger the async load of metadata
101 // trigger the async load of metadata
102 return false;
102 return false;
103 }
103 }
104
104
105 var state = getState('metadata');
105 var state = getState('metadata');
106 var url_data = {
106 var url_data = {
107 'repo_name': templateContext.repo_name,
107 'repo_name': templateContext.repo_name,
108 'commit_id': state.commit_id,
108 'commit_id': state.commit_id,
109 'f_path': state.f_path
109 'f_path': state.f_path
110 };
110 };
111
111
112 var url = pyroutes.url('repo_nodetree_full', url_data);
112 var url = pyroutes.url('repo_nodetree_full', url_data);
113
113
114 metadataRequest = $.ajax({url: url});
114 metadataRequest = $.ajax({url: url});
115
115
116 metadataRequest.done(function(data) {
116 metadataRequest.done(function(data) {
117 $('#file-tree').html(data);
117 $('#file-tree').html(data);
118 timeagoActivate();
118 timeagoActivate();
119 });
119 });
120 metadataRequest.fail(function (data, textStatus, errorThrown) {
120 metadataRequest.fail(function (data, textStatus, errorThrown) {
121 console.log(data);
122 if (data.status != 0) {
121 if (data.status != 0) {
123 alert("Error while fetching metadata.\nError code {0} ({1}).Please consider reloading the page".format(data.status,data.statusText));
122 alert("Error while fetching metadata.\nError code {0} ({1}).Please consider reloading the page".format(data.status,data.statusText));
124 }
123 }
125 });
124 });
126 };
125 };
127
126
128 var callbacks = function() {
127 var initFileJS = function () {
128 var state = getState('callbacks');
129
130 // select code link event
131 $("#hlcode").mouseup(getSelectionLink);
132
133 // file history select2 used for history of file, and switch to
134 var initialCommitData = {
135 at_ref: atRef,
136 id: null,
137 text: '${c.commit.raw_id}',
138 type: 'sha',
139 raw_id: '${c.commit.raw_id}',
140 idx: ${c.commit.idx},
141 files_url: null,
142 };
143
144 // check if we have ref info.
145 var selectedRef = fileTreeRefs[atRef];
146 if (selectedRef !== undefined) {
147 $.extend(initialCommitData, selectedRef)
148 }
149
150 var loadUrl = pyroutes.url('repo_file_history', {'repo_name': templateContext.repo_name, 'commit_id': state.rev,'f_path': state.f_path});
151 var cacheKey = '__SINGLE_FILE_REFS__';
152 var cachedDataSource = {};
153
154 var loadRefsData = function (query) {
155 $.ajax({
156 url: loadUrl,
157 data: {},
158 dataType: 'json',
159 type: 'GET',
160 success: function (data) {
161 cachedDataSource[cacheKey] = data;
162 query.callback({results: data.results});
163 }
164 });
165 };
166
167 var feedRefsData = function (query, cachedData) {
168 var data = {results: []};
169 //filter results
170 $.each(cachedData.results, function () {
171 var section = this.text;
172 var children = [];
173 $.each(this.children, function () {
174 if (query.term.length === 0 || this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0) {
175 children.push(this)
176 }
177 });
178 data.results.push({
179 'text': section,
180 'children': children
181 })
182 });
183
184 query.callback(data);
185 };
186
187 var select2FileHistorySwitcher = function (targetElement, loadUrl, initialData) {
188 var formatResult = function (result, container, query) {
189 return formatSelect2SelectionRefs(result);
190 };
191
192 var formatSelection = function (data, container) {
193 var commit_ref = data;
194
195 var tmpl = '';
196 if (commit_ref.type === 'sha') {
197 tmpl = (commit_ref.raw_id || "").substr(0,8);
198 } else if (commit_ref.type === 'branch') {
199 tmpl = tmpl.concat('<i class="icon-branch"></i> ');
200 tmpl = tmpl.concat(escapeHtml(commit_ref.text));
201 } else if (commit_ref.type === 'tag') {
202 tmpl = tmpl.concat('<i class="icon-tag"></i> ');
203 tmpl = tmpl.concat(escapeHtml(commit_ref.text));
204 } else if (commit_ref.type === 'book') {
205 tmpl = tmpl.concat('<i class="icon-bookmark"></i> ');
206 tmpl = tmpl.concat(escapeHtml(commit_ref.text));
207 }
208 var idx = commit_ref.idx || 0;
209 tmpl = tmpl.concat('<span class="select-index-number">r{0}</span>'.format(idx));
210 return tmpl
211 };
212
213 $(targetElement).select2({
214 dropdownAutoWidth: true,
215 width: "resolve",
216 containerCssClass: "drop-menu",
217 dropdownCssClass: "drop-menu-dropdown",
218 query: function(query) {
219 var cachedData = cachedDataSource[cacheKey];
220 if (cachedData) {
221 feedRefsData(query, cachedData)
222 } else {
223 loadRefsData(query)
224 }
225 },
226 initSelection: function(element, callback) {
227 callback(initialData);
228 },
229 formatResult: formatResult,
230 formatSelection: formatSelection
231 });
232
233 };
234
235 select2FileHistorySwitcher('#file_refs_filter', loadUrl, initialCommitData);
236
237 $('#file_refs_filter').on('change', function(e) {
238 var data = $('#file_refs_filter').select2('data');
239 var commit_id = data.id;
240
241 if ("${c.annotate}" === "True") {
242 var url = pyroutes.url('repo_files:annotated',
243 {'repo_name': templateContext.repo_name,
244 'commit_id': commit_id, 'f_path': state.f_path});
245 } else {
246 var url = pyroutes.url('repo_files',
247 {'repo_name': templateContext.repo_name,
248 'commit_id': commit_id, 'f_path': state.f_path});
249 }
250 window.location = url;
251
252 });
253
254 // show more authors
255 $('#show_authors').on('click', function(e) {
256 e.preventDefault();
257 var url = pyroutes.url('repo_file_authors',
258 {'repo_name': templateContext.repo_name,
259 'commit_id': state.rev, 'f_path': state.f_path});
260
261 $.pjax({
262 url: url,
263 data: 'annotate=${("1" if c.annotate else "0")}',
264 container: '#file_authors',
265 push: false,
266 timeout: 5000
267 }).complete(function(){
268 $('#show_authors').hide();
269 $('#file_authors_title').html(_gettext('All Authors'))
270 })
271 });
272
273 // load file short history
274 $('#file_history_overview').on('click', function(e) {
275 e.preventDefault();
276 path = state.f_path;
277 if (path.indexOf("#") >= 0) {
278 path = path.slice(0, path.indexOf("#"));
279 }
280 var url = pyroutes.url('repo_changelog_file',
281 {'repo_name': templateContext.repo_name,
282 'commit_id': state.rev, 'f_path': path, 'limit': 6});
283 $('#file_history_container').show();
284 $('#file_history_container').html('<div class="file-history-inner">{0}</div>'.format(_gettext('Loading ...')));
285
286 $.pjax({
287 url: url,
288 container: '#file_history_container',
289 push: false,
290 timeout: 5000
291 });
292 });
293
294
295 };
296
297 var initTreeJS = function () {
298 var state = getState('callbacks');
299 getFilesMetadata();
300
301 // fuzzy file filter
302 fileBrowserListeners(state.node_list_url, state.url_base);
303
304 // switch to widget
305 var initialCommitData = {
306 at_ref: atRef,
307 id: null,
308 text: '${c.commit.raw_id}',
309 type: 'sha',
310 raw_id: '${c.commit.raw_id}',
311 idx: ${c.commit.idx},
312 files_url: null,
313 };
314
315 // check if we have ref info.
316 var selectedRef = fileTreeRefs[atRef];
317 if (selectedRef !== undefined) {
318 $.extend(initialCommitData, selectedRef)
319 }
320
321 var loadUrl = pyroutes.url('repo_refs_data', {'repo_name': templateContext.repo_name});
322 var cacheKey = '__ALL_FILE_REFS__';
323 var cachedDataSource = {};
324
325 var loadRefsData = function (query) {
326 $.ajax({
327 url: loadUrl,
328 data: {},
329 dataType: 'json',
330 type: 'GET',
331 success: function (data) {
332 cachedDataSource[cacheKey] = data;
333 query.callback({results: data.results});
334 }
335 });
336 };
337
338 var feedRefsData = function (query, cachedData) {
339 var data = {results: []};
340 //filter results
341 $.each(cachedData.results, function () {
342 var section = this.text;
343 var children = [];
344 $.each(this.children, function () {
345 if (query.term.length === 0 || this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0) {
346 children.push(this)
347 }
348 });
349 data.results.push({
350 'text': section,
351 'children': children
352 })
353 });
354
355 //push the typed in commit idx
356 if (!isNaN(query.term)) {
357 var files_url = pyroutes.url('repo_files',
358 {'repo_name': templateContext.repo_name,
359 'commit_id': query.term, 'f_path': state.f_path});
360
361 data.results.push({
362 'text': _gettext('go to numeric commit'),
363 'children': [{
364 at_ref: null,
365 id: null,
366 text: 'r{0}'.format(query.term),
367 type: 'sha',
368 raw_id: query.term,
369 idx: query.term,
370 files_url: files_url,
371 }]
372 });
373 }
374 query.callback(data);
375 };
376
377 var select2RefFileSwitcher = function (targetElement, loadUrl, initialData) {
378 var formatResult = function (result, container, query) {
379 return formatSelect2SelectionRefs(result);
380 };
381
382 var formatSelection = function (data, container) {
383 var commit_ref = data;
384
385 var tmpl = '';
386 if (commit_ref.type === 'sha') {
387 tmpl = (commit_ref.raw_id || "").substr(0,8);
388 } else if (commit_ref.type === 'branch') {
389 tmpl = tmpl.concat('<i class="icon-branch"></i> ');
390 tmpl = tmpl.concat(escapeHtml(commit_ref.text));
391 } else if (commit_ref.type === 'tag') {
392 tmpl = tmpl.concat('<i class="icon-tag"></i> ');
393 tmpl = tmpl.concat(escapeHtml(commit_ref.text));
394 } else if (commit_ref.type === 'book') {
395 tmpl = tmpl.concat('<i class="icon-bookmark"></i> ');
396 tmpl = tmpl.concat(escapeHtml(commit_ref.text));
397 }
398
399 var idx = commit_ref.idx || 0;
400 tmpl = tmpl.concat('<span class="select-index-number">r{0}</span>'.format(idx));
401 return tmpl
402 };
403
404 $(targetElement).select2({
405 dropdownAutoWidth: true,
406 width: "resolve",
407 containerCssClass: "drop-menu",
408 dropdownCssClass: "drop-menu-dropdown",
409 query: function(query) {
410
411 var cachedData = cachedDataSource[cacheKey];
412 if (cachedData) {
413 feedRefsData(query, cachedData)
414 } else {
415 loadRefsData(query)
416 }
417 },
418 initSelection: function(element, callback) {
419 callback(initialData);
420 },
421 formatResult: formatResult,
422 formatSelection: formatSelection
423 });
424
425 };
426
427 select2RefFileSwitcher('#refs_filter', loadUrl, initialCommitData);
428
429 $('#refs_filter').on('change', function(e) {
430 var data = $('#refs_filter').select2('data');
431 window.location = data.files_url
432 });
433
434 };
435
436 $(document).ready(function() {
129 timeagoActivate();
437 timeagoActivate();
130
438
131 if ($('#trimmed_message_box').height() < 50) {
439 if ($('#trimmed_message_box').height() < 50) {
132 $('#message_expand').hide();
440 $('#message_expand').hide();
133 }
441 }
134
442
135 $('#message_expand').on('click', function(e) {
443 $('#message_expand').on('click', function(e) {
136 $('#trimmed_message_box').css('max-height', 'none');
444 $('#trimmed_message_box').css('max-height', 'none');
137 $(this).hide();
445 $(this).hide();
138 });
446 });
139
447
140 var state = getState('callbacks');
141
142 // VIEW FOR FILE SOURCE
143 if (fileSourcePage) {
448 if (fileSourcePage) {
144 // variants for with source code, not tree view
449 initFileJS()
145
450 } else {
146 // select code link event
451 initTreeJS()
147 $("#hlcode").mouseup(getSelectionLink);
148
149 // file history select2 used for history, and switch to
150 var initialCommitData = {
151 id: null,
152 text: '${_("Pick Commit")}',
153 type: 'sha',
154 raw_id: null,
155 files_url: null
156 };
157
158 select2FileHistorySwitcher('#diff1', initialCommitData, state);
159
160 // show at, diff to actions handlers
161 $('#diff1').on('change', function(e) {
162 $('#diff_to_commit').removeClass('disabled').removeAttr("disabled");
163 $('#diff_to_commit').val(_gettext('Diff to Commit ') + e.val.truncateAfter(8, '...'));
164
165 $('#show_at_commit').removeClass('disabled').removeAttr("disabled");
166 $('#show_at_commit').val(_gettext('Show at Commit ') + e.val.truncateAfter(8, '...'));
167 });
168
169 $('#diff_to_commit').on('click', function(e) {
170 var diff1 = $('#diff1').val();
171 var diff2 = $('#diff2').val();
172
173 var url_data = {
174 repo_name: templateContext.repo_name,
175 source_ref: diff1,
176 source_ref_type: 'rev',
177 target_ref: diff2,
178 target_ref_type: 'rev',
179 merge: 1,
180 f_path: state.f_path
181 };
182 window.location = pyroutes.url('repo_compare', url_data);
183 });
184
185 $('#show_at_commit').on('click', function(e) {
186 var diff1 = $('#diff1').val();
187
188 var annotate = $('#annotate').val();
189 if (annotate === "True") {
190 var url = pyroutes.url('repo_files:annotated',
191 {'repo_name': templateContext.repo_name,
192 'commit_id': diff1, 'f_path': state.f_path});
193 } else {
194 var url = pyroutes.url('repo_files',
195 {'repo_name': templateContext.repo_name,
196 'commit_id': diff1, 'f_path': state.f_path});
197 }
198 window.location = url;
199
200 });
201
202 // show more authors
203 $('#show_authors').on('click', function(e) {
204 e.preventDefault();
205 var url = pyroutes.url('repo_file_authors',
206 {'repo_name': templateContext.repo_name,
207 'commit_id': state.rev, 'f_path': state.f_path});
208
209 $.pjax({
210 url: url,
211 data: 'annotate=${("1" if c.annotate else "0")}',
212 container: '#file_authors',
213 push: false,
214 timeout: 5000
215 }).complete(function(){
216 $('#show_authors').hide();
217 $('#file_authors_title').html(_gettext('All Authors'))
218 })
219 });
220
221 // load file short history
222 $('#file_history_overview').on('click', function(e) {
223 e.preventDefault();
224 path = state.f_path;
225 if (path.indexOf("#") >= 0) {
226 path = path.slice(0, path.indexOf("#"));
227 }
228 var url = pyroutes.url('repo_changelog_file',
229 {'repo_name': templateContext.repo_name,
230 'commit_id': state.rev, 'f_path': path, 'limit': 6});
231 $('#file_history_container').show();
232 $('#file_history_container').html('<div class="file-history-inner">{0}</div>'.format(_gettext('Loading ...')));
233
234 $.pjax({
235 url: url,
236 container: '#file_history_container',
237 push: false,
238 timeout: 5000
239 })
240 });
241
242 }
452 }
243 // VIEW FOR FILE TREE BROWSER
244 else {
245 getFilesMetadata();
246
247 // fuzzy file filter
248 fileBrowserListeners(state.node_list_url, state.url_base);
249
250 // switch to widget
251 var initialCommitData = {
252 at_ref: atRef,
253 id: null,
254 text: '${c.commit.raw_id}',
255 type: 'sha',
256 raw_id: '${c.commit.raw_id}',
257 idx: ${c.commit.idx},
258 files_url: null,
259 };
260
453
261 // check if we have ref info.
262 var selectedRef = fileTreeRefs[atRef];
263 if (selectedRef !== undefined) {
264 $.extend(initialCommitData, selectedRef)
265 }
266
267 var loadUrl = pyroutes.url('repo_refs_data', {'repo_name': templateContext.repo_name});
268 var cacheKey = '__ALL_FILE_REFS__';
269 var cachedDataSource = {};
270
271 var loadRefsData = function (query) {
272 $.ajax({
273 url: loadUrl,
274 data: {},
275 dataType: 'json',
276 type: 'GET',
277 success: function (data) {
278 cachedDataSource[cacheKey] = data;
279 query.callback({results: data.results});
280 }
281 });
282 };
283
284 var feedRefsData = function (query, cachedData) {
285 var data = {results: []};
286 //filter results
287 $.each(cachedData.results, function () {
288 var section = this.text;
289 var children = [];
290 $.each(this.children, function () {
291 if (query.term.length === 0 || this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0) {
292 children.push(this)
293 }
294 });
295 data.results.push({
296 'text': section,
297 'children': children
298 })
299 });
300
301 //push the typed in commit idx
302 if (!isNaN(query.term)) {
303 var files_url = pyroutes.url('repo_files',
304 {'repo_name': templateContext.repo_name,
305 'commit_id': query.term, 'f_path': state.f_path});
306
307 data.results.push({
308 'text': _gettext('go to numeric commit'),
309 'children': [{
310 at_ref: null,
311 id: null,
312 text: 'r{0}'.format(query.term),
313 type: 'sha',
314 raw_id: query.term,
315 idx: query.term,
316 files_url: files_url,
317 }]
318 });
319 }
320 query.callback(data);
321 };
322
323 var select2RefFileSwitcher = function (targetElement, loadUrl, initialData) {
324 var formatResult = function (result, container, query) {
325 return formatSelect2SelectionRefs(result);
326 };
327
328 var formatSelection = function (data, container) {
329 var commit_ref = data;
330
331 var tmpl = '';
332 if (commit_ref.type === 'sha') {
333 tmpl = commit_ref.raw_id.substr(0,8);
334 } else if (commit_ref.type === 'branch') {
335 tmpl = tmpl.concat('<i class="icon-branch"></i> ');
336 tmpl = tmpl.concat(escapeHtml(commit_ref.text));
337 } else if (commit_ref.type === 'tag') {
338 tmpl = tmpl.concat('<i class="icon-tag"></i> ');
339 tmpl = tmpl.concat(escapeHtml(commit_ref.text));
340 } else if (commit_ref.type === 'book') {
341 tmpl = tmpl.concat('<i class="icon-bookmark"></i> ');
342 tmpl = tmpl.concat(escapeHtml(commit_ref.text));
343 }
344
345 tmpl = tmpl.concat('<span class="select-index-number">r{0}</span>'.format(commit_ref.idx));
346 return tmpl
347 };
348
349 $(targetElement).select2({
350 dropdownAutoWidth: true,
351 width: "resolve",
352 containerCssClass: "drop-menu",
353 dropdownCssClass: "drop-menu-dropdown",
354 query: function(query) {
355
356 var cachedData = cachedDataSource[cacheKey];
357 if (cachedData) {
358 feedRefsData(query, cachedData)
359 } else {
360 loadRefsData(query)
361 }
362 },
363 initSelection: function(element, callback) {
364 callback(initialData);
365 },
366 formatResult: formatResult,
367 formatSelection: formatSelection
368 });
369
370 };
371
372 select2RefFileSwitcher('#refs_filter', loadUrl, initialCommitData);
373
374 $('#refs_filter').on('change', function(e) {
375 var data = $('#refs_filter').select2('data');
376 window.location = data.files_url
377 });
378
379 }
380 };
381
382 $(document).ready(function() {
383 callbacks();
384 var search_GET = "${request.GET.get('search','')}";
454 var search_GET = "${request.GET.get('search','')}";
385 if (search_GET === "1") {
455 if (search_GET === "1") {
386 NodeFilter.initFilter();
456 NodeFilter.initFilter();
387 NodeFilter.focus();
457 NodeFilter.focus();
388 }
458 }
389 });
459 });
390
460
391 </script>
461 </script>
392
462
393 </%def> No newline at end of file
463 </%def>
@@ -1,53 +1,64 b''
1
1
2 <div id="codeblock" class="browserblock">
2 <div id="codeblock" class="browserblock">
3 <div class="browser-header">
3 <div class="browser-header">
4 <div class="browser-nav">
4 <div class="browser-nav">
5
5
6 <div class="info_box">
6 <div class="info_box">
7
7
8 <div class="info_box_elem previous">
8 <div class="info_box_elem previous">
9 <a id="prev_commit_link" data-commit-id="${c.prev_commit.raw_id}" class=" ${('disabled' if c.url_prev == '#' else '')}" href="${c.url_prev}" title="${_('Previous commit')}"><i class="icon-left"></i></a>
9 <a id="prev_commit_link" data-commit-id="${c.prev_commit.raw_id}" class=" ${('disabled' if c.url_prev == '#' else '')}" href="${c.url_prev}" title="${_('Previous commit')}"><i class="icon-left"></i></a>
10 </div>
10 </div>
11
11
12 ${h.hidden('refs_filter')}
12 ${h.hidden('refs_filter')}
13
13
14 <div class="info_box_elem next">
14 <div class="info_box_elem next">
15 <a id="next_commit_link" data-commit-id="${c.next_commit.raw_id}" class=" ${('disabled' if c.url_next == '#' else '')}" href="${c.url_next}" title="${_('Next commit')}"><i class="icon-right"></i></a>
15 <a id="next_commit_link" data-commit-id="${c.next_commit.raw_id}" class=" ${('disabled' if c.url_next == '#' else '')}" href="${c.url_next}" title="${_('Next commit')}"><i class="icon-right"></i></a>
16 </div>
16 </div>
17 </div>
17 </div>
18
18
19 % if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name):
19 % if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name):
20 <div title="${_('Add New File')}" class="btn btn-primary new-file">
20 <div>
21 <a href="${h.route_path('repo_files_add_file',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path, _anchor='edit')}">
21 <a class="btn btn-primary new-file" href="${h.route_path('repo_files_add_file',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path, _anchor='edit')}">
22 ${_('Add File')}</a>
22 ${_('Upload File')}
23 </a>
24 <a class="btn btn-primary new-file" href="${h.route_path('repo_files_add_file',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path, _anchor='edit')}">
25 ${_('Add File')}
26 </a>
23 </div>
27 </div>
24 % endif
28 % endif
25
29
26 % if c.enable_downloads:
30 % if c.enable_downloads:
27 <% at_path = '{}'.format(request.GET.get('at') or c.commit.raw_id[:6]) %>
31 <% at_path = '{}'.format(request.GET.get('at') or c.commit.raw_id[:6]) %>
28 <div class="btn btn-default new-file">
32 <div class="btn btn-default new-file">
29 <a href="${h.route_path('repo_archivefile',repo_name=c.repo_name, fname='{}.zip'.format(c.commit.raw_id))}">
33 % if c.f_path == '/':
30 ${_('Download ZIP @ ')} <code>${at_path}</code>
34 <a href="${h.route_path('repo_archivefile',repo_name=c.repo_name, fname='{}.zip'.format(c.commit.raw_id))}">
31 </a>
35 ${_('Download full tree ZIP')}
36 </a>
37 % else:
38 <a href="${h.route_path('repo_archivefile',repo_name=c.repo_name, fname='{}.zip'.format(c.commit.raw_id))}">
39 ${_('Download this tree ZIP')}
40 </a>
41 % endif
32 </div>
42 </div>
33 % endif
43 % endif
34
44
35 <div class="files-quick-filter">
45 <div class="files-quick-filter">
36 <ul class="files-filter-box">
46 <ul class="files-filter-box">
37 <li class="files-filter-box-path">
47 <li class="files-filter-box-path">
38 <i class="icon-search"></i>
48 <i class="icon-search"></i>
39 </li>
49 </li>
40 <li class="files-filter-box-input">
50 <li class="files-filter-box-input">
41 <input onkeydown="NodeFilter.initFilter(event)" class="init" type="text" placeholder="Quick filter" name="filter" size="25" id="node_filter" autocomplete="off">
51 <input onkeydown="NodeFilter.initFilter(event)" class="init" type="text" placeholder="Quick filter" name="filter" size="25" id="node_filter" autocomplete="off">
42 </li>
52 </li>
43 </ul>
53 </ul>
44 </div>
54 </div>
45 </div>
55 </div>
46
56
47 </div>
57 </div>
58
48 ## file tree is computed from caches, and filled in
59 ## file tree is computed from caches, and filled in
49 <div id="file-tree">
60 <div id="file-tree">
50 ${c.file_tree |n}
61 ${c.file_tree |n}
51 </div>
62 </div>
52
63
53 </div>
64 </div>
@@ -1,89 +1,83 b''
1 <%
1 <%
2 if request.GET.get('at'):
2 if request.GET.get('at'):
3 query={'at': request.GET.get('at')}
3 query={'at': request.GET.get('at')}
4 else:
4 else:
5 query=None
5 query=None
6 %>
6 %>
7 <div id="file-tree-wrapper" class="browser-body ${('full-load' if c.full_load else '')}">
7 <div id="file-tree-wrapper" class="browser-body ${('full-load' if c.full_load else '')}">
8 <table class="code-browser rctable repo_summary">
8 <table class="code-browser rctable repo_summary">
9 <thead>
9 <thead>
10 <tr>
10 <tr>
11 <th>${_('Name')}</th>
11 <th>${_('Name')}</th>
12 <th>${_('Size')}</th>
12 <th>${_('Size')}</th>
13 <th>${_('Modified')}</th>
13 <th>${_('Modified')}</th>
14 <th>${_('Last Commit')}</th>
14 <th>${_('Last Commit')}</th>
15 <th>${_('Author')}</th>
15 <th>${_('Author')}</th>
16 </tr>
16 </tr>
17 </thead>
17 </thead>
18
18
19 <tbody id="tbody">
19 <tbody id="tbody">
20 %if c.file.parent:
20 <tr>
21 <tr class="parity0">
21 <td colspan="5">
22 <td class="td-componentname">
22
23 <a href="${h.route_path('repo_files',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.file.parent.path, _query=query)}">
23 ${h.files_breadcrumbs(c.repo_name,c.commit.raw_id,c.file.path, request.GET.get('at'), limit_items=True)}
24 <i class="icon-directory"></i>..
24
25 </a>
26 </td>
25 </td>
27 <td></td>
26 </tr>
28 <td></td>
29 <td></td>
30 <td></td>
31 </tr>
32 %endif
33 %for cnt,node in enumerate(c.file):
27 %for cnt,node in enumerate(c.file):
34 <tr class="parity${cnt%2}">
28 <tr class="parity${cnt%2}">
35 <td class="td-componentname">
29 <td class="td-componentname">
36 % if node.is_submodule():
30 % if node.is_submodule():
37 <span class="submodule-dir">
31 <span class="submodule-dir">
38 % if node.url.startswith('http://') or node.url.startswith('https://'):
32 % if node.url.startswith('http://') or node.url.startswith('https://'):
39 <a href="${node.url}">
33 <a href="${node.url}">
40 <i class="icon-directory browser-dir"></i>${node.name}
34 <i class="icon-directory browser-dir"></i>${node.name}
41 </a>
35 </a>
42 % else:
36 % else:
43 <i class="icon-directory browser-dir"></i>${node.name}
37 <i class="icon-directory browser-dir"></i>${node.name}
44 % endif
38 % endif
45 </span>
39 </span>
46 % else:
40 % else:
47
41
48 <a href="${h.route_path('repo_files',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=h.safe_unicode(node.path), _query=query)}">
42 <a href="${h.route_path('repo_files',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=h.safe_unicode(node.path), _query=query)}">
49 <i class="${('icon-file-text browser-file' if node.is_file() else 'icon-directory browser-dir')}"></i>${node.name}
43 <i class="${('icon-file-text browser-file' if node.is_file() else 'icon-directory browser-dir')}"></i>${node.name}
50 </a>
44 </a>
51 % endif
45 % endif
52 </td>
46 </td>
53 %if node.is_file():
47 %if node.is_file():
54 <td class="td-size" data-attr-name="size">
48 <td class="td-size" data-attr-name="size">
55 % if c.full_load:
49 % if c.full_load:
56 <span data-size="${node.size}">${h.format_byte_size_binary(node.size)}</span>
50 <span data-size="${node.size}">${h.format_byte_size_binary(node.size)}</span>
57 % else:
51 % else:
58 ${_('Loading ...')}
52 ${_('Loading ...')}
59 % endif
53 % endif
60 </td>
54 </td>
61 <td class="td-time" data-attr-name="modified_at">
55 <td class="td-time" data-attr-name="modified_at">
62 % if c.full_load:
56 % if c.full_load:
63 <span data-date="${node.last_commit.date}">${h.age_component(node.last_commit.date)}</span>
57 <span data-date="${node.last_commit.date}">${h.age_component(node.last_commit.date)}</span>
64 % endif
58 % endif
65 </td>
59 </td>
66 <td class="td-hash" data-attr-name="commit_id">
60 <td class="td-hash" data-attr-name="commit_id">
67 % if c.full_load:
61 % if c.full_load:
68 <div class="tooltip" title="${h.tooltip(node.last_commit.message)}">
62 <div class="tooltip" title="${h.tooltip(node.last_commit.message)}">
69 <pre data-commit-id="${node.last_commit.raw_id}">r${node.last_commit.idx}:${node.last_commit.short_id}</pre>
63 <pre data-commit-id="${node.last_commit.raw_id}">r${node.last_commit.idx}:${node.last_commit.short_id}</pre>
70 </div>
64 </div>
71 % endif
65 % endif
72 </td>
66 </td>
73 <td class="td-user" data-attr-name="author">
67 <td class="td-user" data-attr-name="author">
74 % if c.full_load:
68 % if c.full_load:
75 <span data-author="${node.last_commit.author}" title="${h.tooltip(node.last_commit.author)}">${h.gravatar_with_user(request, node.last_commit.author)|n}</span>
69 <span data-author="${node.last_commit.author}" title="${h.tooltip(node.last_commit.author)}">${h.gravatar_with_user(request, node.last_commit.author)|n}</span>
76 % endif
70 % endif
77 </td>
71 </td>
78 %else:
72 %else:
79 <td></td>
73 <td></td>
80 <td></td>
74 <td></td>
81 <td></td>
75 <td></td>
82 <td></td>
76 <td></td>
83 %endif
77 %endif
84 </tr>
78 </tr>
85 %endfor
79 %endfor
86 </tbody>
80 </tbody>
87 <tbody id="tbody_filtered"></tbody>
81 <tbody id="tbody_filtered"></tbody>
88 </table>
82 </table>
89 </div>
83 </div>
@@ -1,41 +1,34 b''
1 <%def name="title(*args)">
1 <%def name="title(*args)">
2 ${_('{} Files').format(c.repo_name)}
2 ${_('{} Files').format(c.repo_name)}
3 %if hasattr(c,'file'):
3 %if hasattr(c,'file'):
4 &middot; ${(h.safe_unicode(c.file.path) or '\\')}
4 &middot; ${(h.safe_unicode(c.file.path) or '\\')}
5 %endif
5 %endif
6
6
7 %if c.rhodecode_name:
7 %if c.rhodecode_name:
8 &middot; ${h.branding(c.rhodecode_name)}
8 &middot; ${h.branding(c.rhodecode_name)}
9 %endif
9 %endif
10 </%def>
10 </%def>
11
11
12 <div>
12 <div>
13
13
14 <div class="summary-detail">
14 <div class="summary-detail">
15 <div class="summary-detail-header">
15 <div class="summary-detail-header">
16 <div class="breadcrumbs files_location">
16
17 <h4>
18 ${h.files_breadcrumbs(c.repo_name,c.commit.raw_id,c.file.path, request.GET.get('at'))}
19 %if c.annotate:
20 - ${_('annotation')}
21 %endif
22 </h4>
23 </div>
24 </div><!--end summary-detail-header-->
17 </div><!--end summary-detail-header-->
25
18
26 % if c.file.is_submodule():
19 % if c.file.is_submodule():
27 <span class="submodule-dir">Submodule ${h.escape(c.file.name)}</span>
20 <span class="submodule-dir">Submodule ${h.escape(c.file.name)}</span>
28 % elif c.file.is_dir():
21 % elif c.file.is_dir():
29 <%include file='files_tree_header.mako'/>
22 <%include file='files_tree_header.mako'/>
30 % else:
23 % else:
31 <%include file='files_source_header.mako'/>
24 <%include file='files_source_header.mako'/>
32 % endif
25 % endif
33
26
34 </div> <!--end summary-detail-->
27 </div> <!--end summary-detail-->
35 % if c.file.is_dir():
28 % if c.file.is_dir():
36 <%include file='files_browser.mako'/>
29 <%include file='files_browser.mako'/>
37 % else:
30 % else:
38 <%include file='files_source.mako'/>
31 <%include file='files_source.mako'/>
39 % endif
32 % endif
40
33
41 </div>
34 </div>
@@ -1,131 +1,148 b''
1 <%namespace name="sourceblock" file="/codeblocks/source.mako"/>
1 <%namespace name="sourceblock" file="/codeblocks/source.mako"/>
2
2
3 <div id="codeblock" class="codeblock">
3 <div id="codeblock" class="browserblock">
4 <div class="codeblock-header">
4 <div class="browser-header">
5 <div class="browser-nav">
6 <div class="pull-left">
7 ## loads the history for a file
8 ${h.hidden('file_refs_filter')}
9 </div>
10
11 <div class="pull-right">
12
13 ## Download
14 % if c.lf_node:
15 <a class="btn btn-default" href="${h.route_path('repo_file_download',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path, _query=dict(lf=1))}">
16 ${_('Download largefile')}
17 </a>
18 % else:
19 <a class="btn btn-default" href="${h.route_path('repo_file_download',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path)}">
20 ${_('Download file')}
21 </a>
22 % endif
23
24 %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name):
25 ## on branch head, can edit files
26 %if c.on_branch_head and c.branch_or_raw_id and not c.file.is_binary:
27 ## binary files are delete only
28 % if c.file.is_binary:
29 ${h.link_to(_('Edit'), '#Edit', class_="btn btn-default disabled tooltip", title=_('Editing binary files not allowed'))}
30 ${h.link_to(_('Delete'), h.route_path('repo_files_remove_file',repo_name=c.repo_name,commit_id=c.branch_or_raw_id,f_path=c.f_path, _anchor='edit'),class_="btn btn-danger")}
31 % else:
32 <a class="btn btn-default" href="${h.route_path('repo_files_edit_file',repo_name=c.repo_name,commit_id=c.branch_or_raw_id,f_path=c.f_path, _anchor='edit')}">
33 ${_('Edit on branch: ')}<code>${c.branch_name}</code>
34 </a>
35
36 <a class="btn btn-danger" href="${h.route_path('repo_files_remove_file',repo_name=c.repo_name,commit_id=c.branch_or_raw_id,f_path=c.f_path, _anchor='edit')}">
37 ${_('Delete')}
38 </a>
39 % endif
40 ## not on head, forbid all
41 % else:
42 ${h.link_to(_('Edit'), '#Edit', class_="btn btn-default disabled tooltip", title=_('Editing files allowed only when on branch head commit'))}
43 ${h.link_to(_('Delete'), '#Delete', class_="btn btn-default btn-danger disabled tooltip", title=_('Deleting files allowed only when on branch head commit'))}
44 % endif
45 %endif
46
47 </div>
48 </div>
49 <div id="file_history_container"></div>
50
51 </div>
52 </div>
53
54 <div class="codeblock codeblock-header">
55 <div>
56 ${h.files_breadcrumbs(c.repo_name,c.commit.raw_id,c.file.path, request.GET.get('at'))}
57 </div>
5 <div class="stats">
58 <div class="stats">
6 <span class="stats-filename">
7 <strong>
8 <i class="icon-file-text"></i>
9 ${c.file.unicode_path_safe}
10 </strong>
11 </span>
12 <span class="item last"><i class="tooltip icon-clipboard clipboard-action" data-clipboard-text="${c.f_path}" title="${_('Copy the full path')}"></i></span>
13 <br/>
14
59
15 % if c.lf_node:
60 % if c.lf_node:
16 <span title="${_('This file is a pointer to large binary file')}"> | ${_('LargeFile')} ${h.format_byte_size_binary(c.lf_node.size)} </span>
61 <span title="${_('This file is a pointer to large binary file')}"> | ${_('LargeFile')} ${h.format_byte_size_binary(c.lf_node.size)} </span>
17 % endif
62 % endif
18
63
19 <div class="stats-info">
64 <div class="stats-info">
20 <span class="stats-first-item">${c.file.lines()[0]} ${_ungettext('line', 'lines', c.file.lines()[0])}</span>
65 <span class="stats-first-item">${c.file.lines()[0]} ${_ungettext('line', 'lines', c.file.lines()[0])}</span>
21 <span> | ${h.format_byte_size_binary(c.file.size)}</span>
66 <span> | ${h.format_byte_size_binary(c.file.size)}</span>
22 <span> | ${c.file.mimetype} </span>
67 <span> | ${c.file.mimetype} </span>
23 <span> | ${h.get_lexer_for_filenode(c.file).__class__.__name__}</span>
68 <span> | ${h.get_lexer_for_filenode(c.file).__class__.__name__}</span>
24 </div>
69 </div>
70
25 </div>
71 </div>
26 <div class="buttons">
72 <div class="pull-right">
27 <a id="file_history_overview" href="#">
73 <a id="file_history_overview" href="#loadHistory">
28 ${_('History')}
74 ${_('History')}
29 </a>
75 </a>
30 <a id="file_history_overview_full" style="display: none" href="${h.route_path('repo_changelog_file',repo_name=c.repo_name, commit_id=c.commit.raw_id, f_path=c.f_path)}">
76 |
31 ${_('Show Full History')}
77 %if c.annotate:
32 </a> |
78 ${h.link_to(_('Source'), h.route_path('repo_files', repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path))}
33 %if c.annotate:
79 %else:
34 ${h.link_to(_('Source'), h.route_path('repo_files', repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path))}
80 ${h.link_to(_('Annotation'), h.route_path('repo_files:annotated',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path))}
35 %else:
81 %endif
36 ${h.link_to(_('Annotation'), h.route_path('repo_files:annotated',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path))}
82 | ${h.link_to(_('Raw'), h.route_path('repo_file_raw',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path))}
37 %endif
38 | ${h.link_to(_('Raw'), h.route_path('repo_file_raw',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path))}
39 |
40 % if c.lf_node:
41 <a href="${h.route_path('repo_file_download',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path, _query=dict(lf=1))}">
42 ${_('Download largefile')}
43 </a>
44 % else:
45 <a href="${h.route_path('repo_file_download',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path)}">
46 ${_('Download')}
47 </a>
48 % endif
49
83
50 %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name):
51 |
52 %if c.on_branch_head and c.branch_or_raw_id and not c.file.is_binary:
53 <a href="${h.route_path('repo_files_edit_file',repo_name=c.repo_name,commit_id=c.branch_or_raw_id,f_path=c.f_path, _anchor='edit')}">
54 ${_('Edit on Branch:{}').format(c.branch_name)}
55 </a>
56 | <a class="btn-danger btn-link" href="${h.route_path('repo_files_remove_file',repo_name=c.repo_name,commit_id=c.branch_or_raw_id,f_path=c.f_path, _anchor='edit')}">${_('Delete')}
57 </a>
58 %elif c.on_branch_head and c.branch_or_raw_id and c.file.is_binary:
59 ${h.link_to(_('Edit'), '#', class_="btn btn-link disabled tooltip", title=_('Editing binary files not allowed'))}
60 | ${h.link_to(_('Delete'), h.route_path('repo_files_remove_file',repo_name=c.repo_name,commit_id=c.branch_or_raw_id,f_path=c.f_path, _anchor='edit'),class_="btn-danger btn-link")}
61 %else:
62 ${h.link_to(_('Edit'), '#', class_="btn btn-link disabled tooltip", title=_('Editing files allowed only when on branch head commit'))}
63 | ${h.link_to(_('Delete'), '#', class_="btn btn-danger btn-link disabled tooltip", title=_('Deleting files allowed only when on branch head commit'))}
64 %endif
65 %endif
66 </div>
84 </div>
67 </div>
85
68 <div id="file_history_container"></div>
69 <div class="code-body">
86 <div class="code-body">
70 %if c.file.is_binary:
87 %if c.file.is_binary:
71 <% rendered_binary = h.render_binary(c.repo_name, c.file)%>
88 <% rendered_binary = h.render_binary(c.repo_name, c.file)%>
72 % if rendered_binary:
89 % if rendered_binary:
73 ${rendered_binary}
90 ${rendered_binary}
74 % else:
91 % else:
75 <div>
92 <div>
76 ${_('Binary file (%s)') % c.file.mimetype}
93 ${_('Binary file (%s)') % c.file.mimetype}
77 </div>
94 </div>
78 % endif
95 % endif
79 %else:
96 %else:
80 % if c.file.size < c.visual.cut_off_limit_file:
97 % if c.file.size < c.visual.cut_off_limit_file:
81 %if c.renderer and not c.annotate:
98 %if c.renderer and not c.annotate:
82 ## pick relative url based on renderer
99 ## pick relative url based on renderer
83 <%
100 <%
84 relative_urls = {
101 relative_urls = {
85 'raw': h.route_path('repo_file_raw',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path),
102 'raw': h.route_path('repo_file_raw',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path),
86 'standard': h.route_path('repo_files',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path),
103 'standard': h.route_path('repo_files',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path),
87 }
104 }
88 %>
105 %>
89 ${h.render(c.file.content, renderer=c.renderer, relative_urls=relative_urls)}
106 ${h.render(c.file.content, renderer=c.renderer, relative_urls=relative_urls)}
90 %else:
107 %else:
91 <table class="cb codehilite">
108 <table class="cb codehilite">
92 %if c.annotate:
109 %if c.annotate:
93 <% color_hasher = h.color_hasher() %>
110 <% color_hasher = h.color_hasher() %>
94 %for annotation, lines in c.annotated_lines:
111 %for annotation, lines in c.annotated_lines:
95 ${sourceblock.render_annotation_lines(annotation, lines, color_hasher)}
112 ${sourceblock.render_annotation_lines(annotation, lines, color_hasher)}
96 %endfor
113 %endfor
97 %else:
114 %else:
98 %for line_num, tokens in enumerate(c.lines, 1):
115 %for line_num, tokens in enumerate(c.lines, 1):
99 ${sourceblock.render_line(line_num, tokens)}
116 ${sourceblock.render_line(line_num, tokens)}
100 %endfor
117 %endfor
101 %endif
118 %endif
102 </table>
119 </table>
103 %endif
120 %endif
104 %else:
121 %else:
105 ${_('File size {} is bigger then allowed limit {}. ').format(h.format_byte_size_binary(c.file.size), h.format_byte_size_binary(c.visual.cut_off_limit_file))} ${h.link_to(_('Show as raw'),
122 ${_('File size {} is bigger then allowed limit {}. ').format(h.format_byte_size_binary(c.file.size), h.format_byte_size_binary(c.visual.cut_off_limit_file))} ${h.link_to(_('Show as raw'),
106 h.route_path('repo_file_raw',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path))}
123 h.route_path('repo_file_raw',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path))}
107 %endif
124 %endif
108 %endif
125 %endif
109 </div>
126 </div>
110 </div>
127 </div>
111
128
112 <script type="text/javascript">
129 <script type="text/javascript">
113 % if request.GET.get('mark'):
130 % if request.GET.get('mark'):
114
131
115 $(function(){
132 $(function(){
116 $(".codehilite").mark(
133 $(".codehilite").mark(
117 "${request.GET.get('mark')}",
134 "${request.GET.get('mark')}",
118 {
135 {
119 "className": 'match',
136 "className": 'match',
120 "accuracy": "complementary",
137 "accuracy": "complementary",
121 "ignorePunctuation": ":._(){}[]!'+=".split(""),
138 "ignorePunctuation": ":._(){}[]!'+=".split(""),
122 "each": function(el) {
139 "each": function(el) {
123 // and also highlight lines !
140 // and also highlight lines !
124 $($(el).closest('tr')).find('td.cb-lineno').addClass('cb-line-selected');
141 $($(el).closest('tr')).find('td.cb-lineno').addClass('cb-line-selected');
125 }
142 }
126 }
143 }
127 );
144 );
128
145
129 });
146 });
130 % endif
147 % endif
131 </script>
148 </script>
@@ -1,84 +1,61 b''
1 <%namespace name="base" file="/base/base.mako"/>
1 <%namespace name="base" file="/base/base.mako"/>
2 <%namespace name="file_base" file="/files/base.mako"/>
2 <%namespace name="file_base" file="/files/base.mako"/>
3
3
4 <div class="summary">
4 <div class="summary">
5 <div class="fieldset">
5 <div class="fieldset">
6 <div class="left-content">
6 <div class="left-content">
7
7
8 <div class="left-content-avatar">
8 <div class="left-content-avatar">
9 ${base.gravatar(c.file_last_commit.author_email, 30)}
9 ${base.gravatar(c.file_last_commit.author_email, 30)}
10 </div>
10 </div>
11
11
12 <div class="left-content-message">
12 <div class="left-content-message">
13 <div class="fieldset collapsable-content no-hide" data-toggle="summary-details">
13 <div class="fieldset collapsable-content no-hide" data-toggle="summary-details">
14 <div class="commit truncate-wrap">${h.urlify_commit_message(h.chop_at_smart(c.commit.message, '\n', suffix_if_chopped='...'), c.repo_name)}</div>
14 <div class="commit truncate-wrap">${h.urlify_commit_message(h.chop_at_smart(c.commit.message, '\n', suffix_if_chopped='...'), c.repo_name)}</div>
15 </div>
15 </div>
16
16
17 <div class="fieldset collapsable-content" data-toggle="summary-details">
17 <div class="fieldset collapsable-content" data-toggle="summary-details">
18 <div class="commit">${h.urlify_commit_message(c.commit.message,c.repo_name)}</div>
18 <div class="commit">${h.urlify_commit_message(c.commit.message,c.repo_name)}</div>
19 </div>
19 </div>
20
20
21 <div class="fieldset" data-toggle="summary-details">
21 <div class="fieldset" data-toggle="summary-details">
22 <div class="" id="file_authors">
22 <div class="" id="file_authors">
23 ## loads single author, or ALL
23 ## loads single author, or ALL
24 <%include file='file_authors_box.mako'/>
24 <%include file='file_authors_box.mako'/>
25 </div>
25 </div>
26 </div>
26 </div>
27 </div>
27 </div>
28
28
29 <div class="fieldset collapsable-content" data-toggle="summary-details">
29 <div class="fieldset collapsable-content" data-toggle="summary-details">
30 <div class="left-label-summary-files">
30 <div class="left-label-summary-files">
31 <p>${_('File last commit')}</p>
31 <p>${_('File last commit')}</p>
32 <div class="right-label-summary">
32 <div class="right-label-summary">
33 <code><a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=c.file_last_commit.raw_id)}">${h.show_id(c.file_last_commit)}</a></code>
33 <code><a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=c.file_last_commit.raw_id)}">${h.show_id(c.file_last_commit)}</a></code>
34
34
35 ${file_base.refs(c.file_last_commit)}
35 ${file_base.refs(c.file_last_commit)}
36 </div>
36 </div>
37 </div>
37 </div>
38 </div>
38 </div>
39
40
41 <div class="fieldset collapsable-content" data-toggle="summary-details">
42 <div class="left-label-summary-files">
43 <p class="spacing">${_('Show/Diff file')}</p>
44 <div class="right-label-summary">
45 ${h.hidden('diff1')}
46 ${h.hidden('diff2',c.commit.raw_id)}
47 ${h.hidden('annotate', c.annotate)}
48 </div>
49 </div>
50 </div>
51
52
53 <div class="fieldset collapsable-content" data-toggle="summary-details">
54 <div class="left-label-summary-files">
55 <p>${_('Action')}</p>
56 <div class="right-label-summary">
57 ${h.submit('diff_to_commit',_('Diff to Commit'),class_="btn disabled",disabled="true")}
58 ${h.submit('show_at_commit',_('Show at Commit'),class_="btn disabled",disabled="true")}
59 </div>
60 </div>
61 </div>
62 </div>
39 </div>
63
40
64 <div class="right-content">
41 <div class="right-content">
65 <div data-toggle="summary-details">
42 <div data-toggle="summary-details">
66 <div class="tags commit-info tags-main">
43 <div class="tags commit-info tags-main">
67 <code><a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=c.commit.raw_id)}">${h.show_id(c.commit)}</a></code>
44 <code><a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=c.commit.raw_id)}">${h.show_id(c.commit)}</a></code>
68 ${file_base.refs(c.commit)}
45 ${file_base.refs(c.commit)}
69 </div>
46 </div>
70 </div>
47 </div>
71 </div>
48 </div>
72
49
73 <div class="clear-fix"></div>
50 <div class="clear-fix"></div>
74
51
75 <div class="btn-collapse" data-toggle="summary-details">
52 <div class="btn-collapse" data-toggle="summary-details">
76 ${_('Show More')}
53 ${_('Show More')}
77 </div>
54 </div>
78
55
79 </div>
56 </div>
80 </div>
57 </div>
81
58
82 <script>
59 <script>
83 collapsableContent();
60 collapsableContent();
84 </script>
61 </script>
General Comments 0
You need to be logged in to leave comments. Login now