8000 Added a default ide file link web view · symfony/symfony@a0267a7 · GitHub
[go: up one dir, main page]

Skip to content

Commit a0267a7

Browse files
jeremyFreeAgentnicolas-grekas
authored andcommitted
Added a default ide file link web view
1 parent b359263 commit a0267a7

File tree

8 files changed

+145
-9
lines changed

8 files changed

+145
-9
lines changed

src/Symfony/Bridge/Twig/Extension/CodeExtension.php

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -130,27 +130,36 @@ public function formatArgsAsText($args)
130130
/**
131131
* Returns an excerpt of a code file around the given line number.
132132
*
133-
* @param string $file A file path
134-
* @param int $line The selected line number
133+
* @param string $file A file path
134+
* @param int $line The selected line number
135+
* @param int $srcContext The number of displayed lines around or -1 for the whole file
135136
*
136137
* @return string An HTML string
137138
*/
138-
public function fileExcerpt($file, $line)
139+
public function fileExcerpt($file, $line, $srcContext = 3)
139140
{
140141
if (is_readable($file)) {
141142
// highlight_file could throw warnings
142143
// see https://b 8000 ugs.php.net/bug.php?id=25725
143144
$code = @highlight_file($file, true);
144145
// remove main code/span tags
145146
$code = preg_replace('#^<code.*?>\s*<span.*?>(.*)</span>\s*</code>#s', '\\1', $code);
146-
$content = preg_split('#<br />#', $code);
147+
// split multiline spans
148+
$code = preg_replace_callback('#<span ([^>]++)>((?:[^<]*+<br \/>)++[^<]*+)</span>#', function ($m) {
149+
return "<span $m[1]>".str_replace('<br />', "</span><br /><span $m[1]>", $m[2]).'</span>';
150+
}, $code);
151+
$code = explode('<br />', $code);
147152

148153
$lines = array();
149-
for ($i = max($line - 3, 1), $max = min($line + 3, count($content)); $i <= $max; ++$i) {
150-
$lines[] = '<li'.($i == $line ? ' class="selected"' : '').'><code>'.self::fixCodeMarkup($content[$i - 1]).'</code></li>';
154+
if (0 > $srcContext) {
155+
$srcContext = count($code);
151156
}
152157

153-
return '<ol start="'.max($line - 3, 1).'">'.implode("\n", $lines).'</ol>';
158+
for ($i = max($line - $srcContext, 1), $max = min($line + $srcContext, count($code)); $i <= $max; ++$i) {
159+
$lines[] = '<li'.($i == $line ? ' class="selected"' : '').'><div class="anchor" id="line'.$i.'"></div><code>'.self::fixCodeMarkup($code[$i - 1]).'</code></li>';
160+
}
161+
162+
return '<ol start="'.max($line - $srcContext, 1).'">'.implode("\n", $lines).'</ol>';
154163
}
155164
}
156165

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public function getConfigTreeBuilder()
8787
->end()
8888
->end()
8989
->end()
90-
->scalarNode('ide')->defaultNull()->end()
90+
->scalarNode('ide')->defaultValue('symfony')->end()
9191
->booleanNode('test')->end()
9292
->scalarNode('default_locale')->defaultValue('en')->end()
9393
->arrayNode('trusted_hosts')

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ public function load(array $configs, ContainerBuilder $container)
100100
'macvim' => 'mvim://open?url=file://%%f&line=%%l',
101101
'emacs' => 'emacs://open?url=file://%%f&line=%%l',
102102
'sublime' => 'subl://open?url=file://%%f&line=%%l',
103+
'symfony' => '/_profiler/open?file=%%f&line=%%l#line%%l#'.json_encode(dirname($container->getParameter('kernel.root_dir')).DIRECTORY_SEPARATOR).':""',
103104
);
104105
$ide = $config['ide'];
105106

src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class ProfilerController
3535
private $templates;
3636
private $toolbarPosition;
3737
private $cspHandler;
38+
private $kernelRootDir;
3839

3940
/**
4041
* Constructor.
@@ -44,15 +45,17 @@ class ProfilerController
4445
* @param \Twig_Environment $twig The twig environment
4546
* @param array $templates The templates
4647
* @param string $toolbarPosition The toolbar position (top, bottom, normal, or null -- use the configuration)
48+
* @param string $kernelRootDir The Kernel root directory
4749
*/
48-
public function __construct(UrlGeneratorInterface $generator, Profiler $profiler = null, \Twig_Environment $twig, array $templates, $toolbarPosition = 'normal', ContentSecurityPolicyHandler $cspHandler = null)
50+
public function __construct(UrlGeneratorInterface $generator, Profiler $profiler = null, \Twig_Environment $twig, array $templates, $toolbarPosition = 'normal', ContentSecurityPolicyHandler $cspHandler = null, $kernelRootDir = null)
4951
{
5052
$this->generator = $generator;
5153
$this->profiler = $profiler;
5254
$this->twig = $twig;
5355
$this->templates = $templates;
5456
$this->toolbarPosition = $toolbarPosition;
5557
$this->cspHandler = $cspHandler;
58+
$this->kernelRootDir = $kernelRootDir;
5659
}
5760

5861
/**
@@ -394,6 +397,40 @@ public function phpinfoAction()
394397
return new Response($phpinfo, 200, array('Content-Type' => 'text/html'));
395398
}
396399

400+
/**
401+
* Displays the source of a file.
402+
*
403+
* @return Response A Response instance
404+
*
405+
* @throws NotFoundHttpException
406+
*/
407+
public function openAction(Request $request)
408+
{
409+
if (null === $this->kernelRootDir) {
410+
throw new NotFoundHttpException('KernelRootDir should be set.');
411+
}
412+
413+
if (null === $this->profiler) {
414+
throw new NotFoundHttpException('The profiler must be enabled.');
415+
}
416+
$this->profiler->disable();
417+
418+
$file = $request->query->get('file');
419+
$line = $request->query->get('line');
420+
421+
$filename = dirname($this->kernelRootDir).DIRECTORY_SEPARATOR.$file;
422+
423+
if (preg_match("'(^|[/\\\\])\.\.?([/\\\\]|$)'", $file) || !is_readable($filename)) {
424+
throw new NotFoundHttpException(sprintf('The file "%s" cannot be opened.', $filename));
425+
}
426+
427+
return new Response($this->twig->render('@WebProfiler/Profiler/open.html.twig', array(
428+
'file' => $file,
429+
'filename' => $filename,
430+
'line' => $line,
431+
)), 200, array('Content-Type' => 'text/html'));
432+
}
433+
397434
/**
398435
* Gets the Template Manager.
399436
*

src/Symfony/Bundle/WebProfilerBundle/Resources/config/profiler.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
<argument>%data_collector.templates%</argument>
1313
<argument>%web_profiler.debug_toolbar.position%</argument>
1414
<argument type="service" id="web_profiler.csp.handler" />
15+
<argument>%kernel.root_dir%</argument>
1516
</service>
1617

1718
<service id="web_profiler.controller.router" class="Symfony\Bundle\WebProfilerBundle\Controller\RouterController">

src/Symfony/Bundle/WebProfilerBundle/Resources/config/routing/profiler.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828
<default key="_controller">web_profiler.controller.profiler:searchResultsAction</default>
2929
</route>
3030

31+
<route id="_open" path="/open">
32+
<default key="_controller">web_profiler.controller.profiler:openAction</default>
33+
</route>
34+
3135
<route id="_profiler" path="/{token}">
3236
<default key="_controller">web_profiler.controller.profiler:panelAction</default>
3337
</route>
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
{# Mixins
2+
========================================================================= #}
3+
{% set mixins = {
4+
'break_long_words': '-ms-word-break: break-all; word-break: break-all; word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto;',
5+
'monospace_font': 'font-family: monospace; font-size: 13px; font-size-adjust: 0.5;',
6+
'sans_serif_font': 'font-family: Helvetica, Arial, sans-serif;',
7+
'subtle_border_and_shadow': 'background: #FFF; border: 1px solid #E0E0E0; box-shadow: 0px 0px 1px rgba(128, 128, 128, .2);'
8+
} %}
9+
10+
{# Normalization
11+
(normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css)
12+
========================================================================= #}
13+
html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}
14+
15+
{# Basic styles
16+
========================================================================= #}
17+
html, body {
18+
height: 100%;
19+
width: 100%;
20+
}
21+
body {
22+
background-color: #F9F9F9;
23+
color: #aaa;
24+
display: flex;
25+
flex-direction: column;
26+
{{ mixins.sans_serif_font|raw }}
27+
font-size: 14px;
28+
line-height: 1.4;
29+
}
30+
.header {
31+
background-color: #222;
32+
position: fixed;
33+
top: 0;
34+
width: 100%;
35+
}
36+
.header h1 {
37+
float: left;
38+
color: #FFF;
39+
font-weight: normal;
40+
font-size: 21px;
41+
margin: 0;
42+
padding: 10px 10px 8px;
43+
}
44+
45+
a.doc {
46+
float: right;
47+
color: #FFF;
48+
text-decoration: none;
49+
}
50+
51+
a.doc:hover {
52+
text-decoration: underline;
53+
}
54+
55+
.source {
56+
margin-top: 41px;
57+
}
58+
59+
.source li.selected {
60+
background: rgba(255, 255, 153, 0.5);
61+
}
62+
63+
.anchor {
64+
position: relative;
65+
top: -7em;
66+
visibility: hidden;
67+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{% extends '@WebProfiler/Profiler/base.html.twig' %}
2+
3+
{% block head %}
4+
<style>
5+
{{ include('@WebProfiler/Profiler/open.css.twig') }}
6+
</style>
7+
{% endblock %}
8+
9+
{% block body %}
10+
<div class="header">
11+
<a class="doc" href="https://symfony.com/doc/{{ constant('Symfony\\Component\\HttpKernel\\Kernel::VERSION') }}/reference/configuration/framework.html#ide" rel="help">Open in your IDE?</a>
12+
<h1>{{ file }} <small>line {{ line }}</small></h1>
13+
</div>
14+
<div class="source">
15+
{{ filename|file_excerpt(line, -1) }}
16+
</div>
17+
{% endblock %}

0 commit comments

Comments
 (0)
0