I search a way to parse strings in TWIG.
I have a translation file: messages.fr.yml and I call strings like that: {{ 'bloc.name'|trans() | raw }}.
In french, before some punctuation markers there is a space. The problem is when the sentence is cut between the end ant the marker. So I want to replace each space before these markers: [ ? , ! , ; , : ] by .
I though about a solution which could use autoescape + regex but I do not know how can I do that and if it is the best way to do. Someone has an idea?
Thank you for your help!
You are looking for : how to create your own Twig Filter.
It is possible with a Twig Extension : http://symfony.com/doc/current/cookbook/templating/twig_extension.html
// src/AppBundle/Twig/AppExtension.php
namespace AppBundle\Twig;
class AppExtension extends \Twig_Extension
{
public function getFilters()
{
return array(
new \Twig_SimpleFilter('nbspace', array($this, 'nbspace'))
);
}
public function nbspace($sentence)
{
return preg_replace('/ ([\?!;:])/',' $1',$sentence);
}
public function getName()
{
return 'app_extension';
}
}
Then you have to enable this filter in services.yml like this :
# app/config/services.yml
services:
app.twig_extension:
class: AppBundle\Twig\AppExtension
public: false
tags:
- { name: twig.extension }
To use it :
{{ 'bloc.name'|trans() | nbspace | raw }}
No need to change the autoescaping stategy in your use case.
If you want to avoid the 'raw' filter, you can also specify that your filter returns something 'safe for html' :
new \Twig_SimpleFilter('nbspace', array($this, 'nbspace'), array('is_safe'=>array('html')))
Related
I'm trying to generate some C# code using Scriban templates. The DB I'm using is postgresql, so my tables and properties are all in snake_case. I managed to make a function to convert snake case to pascal case:
{{ for word in EntityName | string.split "_" -}} {{~word | string.capitalize}} {{-end}}
This does convert entity_name to the desired EntityName.
And camel case:
{{func split(en)
ret en | string.split "_"
end}}
{{for index in 0..#split(EntityName).size -}}
{{-if index == 0}} {{~#split(EntityName)[index]-}} {{-else-}} {{-#split(EntityName)[index] | string.capitalize-}} {{-end-}}
{{-end}}
However, I need to use this function multiple times in my template, therefore I wanted to make a function I can use throughout the template, just like the split(en) function I use for the camel case conversion. So I could do something like this everywhere I need it:
{{ #convert(EntityName) }}
Is this possible, and if yes, how?
Any help would be appreciated!
I found another solution to my problem. Instead of creating functions in the template itself, I make a ScriptObject.
public class ScribanHelper : ScriptObject
{
public static string ConvertToPascalCase(string word)
{
if (string.IsNullOrEmpty(word))
return string.Empty;
return string.Join("", word.Split('_')
.Select(w => w.Trim())
.Where(w => w.Length > 0)
.Select(w => w.Substring(0, 1).ToUpper() + w.Substring(1).ToLower()));
}
}
And then I push this to the scriban context to use it in the templates.
var context = new TemplateContext { MemberRenamer = member => member.Name };
var scriptObject = new ScribanHelper();
context.PushGlobal(scriptObject);
var templateString = File.ReadAllText(templateSetting.Name);
var template = Template.Parse(templateString);
var entityScriptObject = new ScriptObject();
entityScriptObject.Import(entity, renamer: member => member.Name);
context.PushGlobal(entityScriptObject);
var result = template.Render(context);
And then I can easily use it in the templates.
{{-func pc(name)
ret convert_to_pascal_case name
end}}
{{#pc(EntityName)}}
You can try this https://github.com/Humanizr/Humanizer. You still need to create the function and can use word.Pascalize() inside it.
I have a unique situation where I need to query a mongo database to find the names of people who occur in a body of text. The query must specify the body of text and find records with values that occur in the body of text. How can I do this with a regular expression?
I need to write a query where this would match:
/Jonathan is a handsome guy/.test('Jonathan')
The problem is that the text inside "test" is the value of a mongo field, so this query must be written such that the body of text is provided as input, and it matches on names that occur within (are substrings of) the body of text.
A more concrete example:
db.test.find();
{ "_id" : ObjectId("547e9b79f2b519cd1657b21e"), "name" : "Jonathan" }
{ "_id" : ObjectId("547e9b88f2b519cd1657b21f"), "name" : "Sandy" }
db.test.find({name: { $in: [/Jonathan has the best queries/]} } );
I need to construct a query that would return "Jonathan" when provided the input "Jonathan has the best queries"
This $where may do the trick, though can be very slow:
db.test.find({$where: function() {
var mystr = '/Jonathan has the best queries/';
var patt = new RegExp(this.name);
if (patt.test(mystr)) return true;
return false;
}})
I defined a copyField and called it:"IsIntranet" and i know my users in intranet using 192.168.* Ip
I wanna set value true if my regex matched in IsIntranet copy field and if not i set false to that
this is my regex (192\.168\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))
how can i do such a thing?
If you need any more information i can Edit my Question.
Thank you.
It seems you are looking for a conditional copyField.
You can do this by creating a subclass of UpdateRequestProcessorFactory.
You can then override the processAdd method to add to your isIntranet field if it matches the regex.
public void processAdd(AddUpdateCommand cmd) throws IOException {
SolrInputDocument doc = cmd.getSolrInputDocument();
Object v = doc.getFieldValue( "ip" );
if( v != null ) {
String regexPattern = "(192\.168\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))"
if( Pattern.matches(regexPattern, v) ) {
doc.addField( "IsIntranet", true );
}
}
super.processAdd(cmd);
}
You can find the whole example here.
My IDE PHPstorm allows you to do search and replace using regex, one of the things I find myself often doing is switching the order or action, aka, in function a I will set a value on items from list a using list b as the values.
but then in function b I want to invert it.
so I want to set a value on items from list b using list a as the values.
A proper example is this:
var $clipDetailsGame = $('#clipDetailsGame');
var $clipDetailsTitle = $('#clipDetailsTitle');
var $clipDetailsByline = $('#clipDetailsByline');
var $clipDetailsTeamOne = $('#clipDetailsTeamOne');
var $clipDetailsTeamTwo = $('#clipDetailsTeamTwo');
var $clipDetailsReferee = $('#clipDetailsReferee');
var $clipDetailsDescription = $('#clipDetailsDescription');
var $clipDetailsCompetition = $('#clipDetailsCompetition');
function a(clip){
clip.data('gameId' , $clipDetailsGame.val());
clip.data('title' , $clipDetailsTitle.val());
clip.data('byline' , $clipDetailsByline.val());
clip.data('team1' , $clipDetailsTeamOne.val());
clip.data('team2' , $clipDetailsTeamTwo.val());
clip.data('refereeId' , $clipDetailsReferee.val());
clip.data('description' , $clipDetailsDescription.val());
clip.data('competitionId', $clipDetailsCompetition.val());
}
function b (clip){
$clipDetailsGame .val(clip.data('gameId'));
$clipDetailsTitle .val(clip.data('title'));
$clipDetailsByline .val(clip.data('byline'));
$clipDetailsTeamOne .val(clip.data('team1'));
$clipDetailsTeamTwo .val(clip.data('team2'));
$clipDetailsReferee .val(clip.data('refereeId'));
$clipDetailsDescription.val(clip.data('description'));
$clipDetailsCompetition.val(clip.data('competitionId'));
}
Excluding the formatting (It's just there to make my point clearer), what kind of regex could I use to do the replacement for me?
Basic regex -- nothing fancy or complex at all
Search for: (clip\.data\('[a-zA-Z0-9]+')\s*, (\$[a-zA-Z0-9]+\.val\()(\)\);)
Replace with: \$2\$1\$3
The only PhpStorm-related thing here is replacement string format -- you have to "escape" $ to have it work (i.e. it has to be \$2 to use 2nd back-trace instead of just $2 or \2 (as used in other engines)).
This will transform this:
clip.data('gameId' , $clipDetailsGame.val());
clip.data('title' , $clipDetailsTitle.val());
clip.data('byline' , $clipDetailsByline.val());
clip.data('team1' , $clipDetailsTeamOne.val());
clip.data('team2' , $clipDetailsTeamTwo.val());
clip.data('refereeId' , $clipDetailsReferee.val());
clip.data('description' , $clipDetailsDescription.val());
clip.data('competitionId', $clipDetailsCompetition.val());
into this:
$clipDetailsGame.val(clip.data('gameId'));
$clipDetailsTitle.val(clip.data('title'));
$clipDetailsByline.val(clip.data('byline'));
$clipDetailsTeamOne.val(clip.data('team1'));
$clipDetailsTeamTwo.val(clip.data('team2'));
$clipDetailsReferee.val(clip.data('refereeId'));
$clipDetailsDescription.val(clip.data('description'));
$clipDetailsCompetition.val(clip.data('competitionId'));
Useful link: http://www.jetbrains.com/phpstorm/webhelp/regular-expression-syntax-reference.html
Mopping up (not quite the answer to this question, but another way of organizing the code to make search and replace unnecessary):
var $details = {};
var fields = [
'Game', 'Title', 'Byline', 'TeamOne', 'TeamTwo', 'Referee', 'Description',
'Competition'
];
for(field in fields) {
$details[field] = $('#clipDetails' + field);
}
function a(clip) {
for(field in fields) {
clip.data(field, $details[fields].val());
}
}
function b(clip) {
for(field in fields) {
$details[field].val(clip.data(field));
}
}
Yes, I know that there are tiny naming inconsistencies that means that this isn't working out of the box, such as Game versus gameId. This is an excellent occasion to clean that up too :). If you still want to keep the title case for the ids (such as #clipDetailsGame in stead of #clipDetailsgame), keep it in title case in the fields array and use toLowerCase where you need lower case.
By the way, there is an interesting read on what makes DRY a good thing here: https://softwareengineering.stackexchange.com/questions/103233/why-is-dry-important
I am using tinymce editor for inserting contents to mysql.
I have changed wordpress gallery editor plugin according to my system.
If there is gallery code in content. I convert this code to a symbolic photo, so that user understand there is a gallery , in stead of seeing a code. Like wordpress does.
If there is only 1 gallery in content, i convert this code to image successfully, but if there is more than 1 gallery it fails.
How can i convert all {gallery} code into a symbolic image before saving to db and convert these photos back to {gallery} code again while inserting or updating into mysql.
I am so bad on regular expression.
I think do_gallery RegExp has mistake. How should i change this.
initalising editor like:
ed.onBeforeSetContent.add(function(ed, o) {
ed.dom.loadCSS(url + "/css/gallery.css");
o.content = t._do_gallery(o.content);
});
ed.onPostProcess.add(function(ed, o) {
if (o.get)
o.content = t._get_gallery(o.content);
});
My "do and get gallery" codes like that:
_do_gallery : function(co) {
return co.replace(/\{gallery([^\]]*)\}/g, function(a,b){
var image = '<img src="gallery.gif" class="wpGallery mceItem" title="gallery'+tinymce.DOM.encode(b)+'" />';
console.log(image);
return image;
});
},
_get_gallery : function(co) {
function getAttr(s, n) {
n = new RegExp(n + '="([^"]+)"', 'g').exec(s);
return n ? tinymce.DOM.decode(n[1]) : '';
};
return co.replace(/(?:<p{^>}*>)*(<img[^>]+>)(?:<\/p>)*/g, function(a,im) {
var cls = getAttr(im, 'class');
if ( cls.indexOf('wpGallery') != -1 )
return '<p>{'+tinymce.trim(getAttr(im, 'title'))+'}</p>';
return a;
});
}
If Content is:
<p>Blah</p>
<p>{gallery Name="gallery1" id="82" galeryID="15" sizeId="6" galery_type="list"}</p>
<p>test</p>
this is ok
<img src="gallery.gif" class="wpGallery mceItem" title="gallery Name="tekne1" id="82" galeryID="15" sizeId="6" galery_type="liste"" />
But, if content is:
<p>Blah</p>
<p>{gallery Name="gallery1" id="82" galeryID="15" sizeId="6" galery_type="list"}</p>
<p>test</p>
<p>{gallery Name="gallery2" id="88" galeryID="11" sizeId="1" galery_type="slide"}</p>
<p>test2</p>
it logs
<img src="gallery.gif" class="wpGallery mceItem" title="gallery Name="gallery1" id="82" galeryID="15" sizeId="6" galery_type="list"}</p> <p>test</p> <p>{gallery Name="gallery2" id="88" galeryID="11" sizeId="1" galery_type="slide"" />
I hope i could explain my problem
Thank you.
I suspect that your original regex is a typo, looks like a missing Shift when you hit the ]. Try this:
/\{gallery([^\}]*)\}/g
Then the ([^\}]*) part will (greedily) eat up any sequence of characters that aren't }; your original one would consume any sequence of character that didn't include a ] and the result is that you'd grab everything between the first { and the last } rather than just grabbing the text between pairs of braces.