I have the following CSS code:
#np-toolbar-l a{ position: relative; padding: 0px 8px; line-height: 30px; display: inline-block; font-size: 12px; }
#np-toolbar-l a:hover{ background-color: #EFEFEF; opacity: 0.7; }
#np-toolbar-l a *:hover{ cursor: pointer; }
/** Icon */
#np-toolbar [class^="icon-"]{ font-size: 18px; vertical-align: middle; margin-right: 5px; }
I am trying to replace np-toolbar to another ID,
I just want to match np-toolbar not np-toolbar-l or something like this,
here's a tutoral about how to capture all the IDs from CSS:
#-?[_a-zA-Z]+[_a-zA-Z0-9-]*(?=[^}]*\{)
source: Regex to match ids in a css file?
I couldn't find out how do I search a "compelete ID" by regex,
here's my example: (It'll still count np-toolbar-l in)
/(?<=(#|\.))(np-toolbar)+(?=( |:||\[))/
EDIT: ummm, jsut added some symbols behind it,
it looks like the answer which I am looking for
/(?<=(#|\.))(np-toolbar)+(?=( |:|\[|\{|\.|,))/
If you're looking for a specific ID, you can greatly simplify your regex:
/(#np-toolbar)(?=[{.,\s])/g
That should find the ID wherever it appears in the CSS. It first matches the ID exactly, then only allows { (for beginning the style), , (for listing selectors), . (for appended classes), or space/tab/newline characters afterwards, preventing it from matching IDs like np-toolbar-1 etc.
Maybe you could try this regexp:
/#np-toolbar(?![-\w])/
which means: match all "#np-toolbar" inclusions if inclusion doesn't end with "-" or any \w symbol
Related
I am working on a PHP script that takes a plain text file task list and parses things like:
Project name heading because it ends with a semi-colon: == a project
Tasks begin with a - task name
#tag-name gets wrapped with <span class="tag">#tag-name</span>
#done gets wrapped with <span class="tag done">#done</span>
and more
This PHP function below is what does the replacements...
function get_marked_up_todo($todo){
$todo = htmlspecialchars($todo,ENT_QUOTES)."\n\n";
$search = array('/(.+:)(.+)\n\n/sU', // Get projects
'/(- ([^\#\n]+).+)/', // Get todos
'/(.+:)/', // Get headings
'/\n([^\<\n].+)/', // Get notes
'/- (.+#done)/', // Get done
'/(#due\([^\)]+\))/', // Get due tags
'/(#(?!due)[^\s]+)/', // Get tags
"/\t/",
'/`(.*?)`/', // inline code
);
$replace = array("<div class=\"project\">\n$1$2\n</div>\n\n",
'<span class="todo"><input type="checkbox" value="'.trim('\2').'"> \1</span>',
'<h1>\1</h1>',
"\n\t<span class=\"note\">$1</span>",
'<span class="bullet-done">? ? ??</span> - <strike>\1</strike>',
'<span class="tag due">\1</span>',
'<span class="tag">\1</span>',
"\t<span class=\"tab\"></span>",
'<code>\1</code>',
);
return preg_replace($search, $replace, $todo);
}
In the above search and replace arrays the very last item in both arrays is a new pattern I added to find inline code wrapped in backticks like Markdown inline code.
The problem is, on the output each task item row gets a checkbox input field added to the front of the task row and in the value of this checkbox my code is being parsed.
All the other replacement RegEx does not show up in the checkbox values only when I add an item like this inline code or any other item I have added such as RegEx for bold text and italic.
Why does mine show up in the checkbox value HTML and none of the others do?
I have setup a demo to show the output here of the PHP -
https://3v4l.org/f0e8W#output
Here is the full code as well
<?php
echo "<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>TODO.todo</title></head>
<body>
<style>
.project {
line-height: 4px;
}
.bullet-done {
font-weight: bold;
font-style: normal;
color: rgba(0,114,62,1.0);
}
.note{
display: block;
color: rgba(133,130,102,1.0);
font-weight: normal;
font-style: normal;
}
.todo {
display: inline-block;
}
.tag {
font-weight: bold;
font-style: normal;
color: rgba(160,46,43,0.6);
}
body {
background: rgba(239,233,183,1.0);
color: rgba(0,0,0,0.31);
font-weight: normal;
font-style: normal;
}
h1 {
font-weight: bold;
font-style: normal;
background: rgba(0,0,0,0.06);
color: rgba(188,100,74,1.0);
width: 100%;
line-height: 34px;
}
.tab{
display: inline-block;
width:0px;
height: 0px;
background: #000000;
</style><pre>";
$todo = 'Version 1:
This file is in TaskPaper format.
Tabs are used to indent.
Each task begins with a "- ".
Projects end with a ":".
Tags are in the format "#tag_name".
All other lines (such as these) are considered as notes,
and are to be ignored.
- User signup
- Register for an account
- Log in #done
- Forget password
- Manage users
- Create users #in_progress
- Delete users
- User profile page #40%
- Blog
- Creating new posts #done
- Comments #done
- Moderating comments #done
This is my todo list:
This is a note about the list.
- this is an item #done
- and this is #me
this is a note about my done item
- this is the last #java #shopping #item #done
This is a second list:
- Add more funk to something #work #java
- Send something somewhere #work #email #due(12 Aug 07)
- this is an example
- dfgdfg
ggg
hfghf
- hgh
- dfygdfgdf
List:
- gdfgdf `inline code` hhf
- gdfgdf
- dfgdfg #done
';
echo get_marked_up_todo($todo);
echo '</pre></body></html>';
function get_marked_up_todo($todo){
$todo = htmlspecialchars($todo,ENT_QUOTES)."\n\n";
$search = array('/(.+:)(.+)\n\n/sU', // Get projects
'/(- ([^\#\n]+).+)/', // Get todos
'/(.+:)/', // Get headings
'/\n([^\<\n].+)/', // Get notes
'/- (.+#done)/', // Get done
'/(#due\([^\)]+\))/', // Get due tags
'/(#(?!due)[^\s]+)/', // Get tags
"/\t/",
'/`(.*?)`/', // inline code
);
$replace = array("<div class=\"project\">\n$1$2\n</div>\n\n",
'<span class="todo"><input type="checkbox" value="'.trim('\2').'"> \1</span>',
'<h1>\1</h1>',
"\n\t<span class=\"note\">$1</span>",
'<span class="bullet-done">? ? ??</span> - <strike>\1</strike>',
'<span class="tag due">\1</span>',
'<span class="tag">\1</span>',
"\t<span class=\"tab\"></span>",
'<code>\1</code>',
);
return preg_replace($search, $replace, $todo);
}
If I understood the issue correctly, your issue is that when you use your own replacement for <code>, the <input> tag looks like this:
<input type="checkbox" value="gdfgdf <code>inline code</code> hh">
but you want to it to NOT include the <code>...</code> part, like this:
<input type="checkbox" value="gdfgdf ">.
If my understanding is correct, then you fix you simply need to fix the RegExp that's in charge of rendering the <input> tag, which is this one:
'/(- ([^\#\n]+).+)/', // Get todos
The way it works is by taking everything from - until either a # or a newline (\n) shows up. You want to add do it the backtick:
'/(- ([^\#\n]+).+)/', // Get todos
This will make the RegExp stop capturing when it encounters the first ` and will fix your issue (again, if I understood it correctly).
can i know how to remove date part from a blogger post
for ex check the below url: http://w2t-minit.blogspot.in/2015/03/photoshop-effects-part-2.html but i want that to be like below url http://w2t-minit.blogspot.in/photoshop-effects-part-2.html
i dont want the date part “2015/03” to be posted can you help me how to remove that ??
thanks
Unfortunately, it's impossible on Blogger.
Split the absolute url, and extract the parts with REGEXP :
$url = parse_url('http://w2t-minit.blogspot.in/2015/03/photoshop-effects-part-2.html');
preg_match('#\/\d{4}\/\d{2}\/(?P<url>.*)#', $url['path'], $matches);
$matches['url'] will contain photoshop-effects-part-2.html . then re-assemble a full url :
$dateless = $url['scheme'] .'://'. $url['host'] .'/'.$matches['url'];
EDIT : I think I have misunderstood the question here.
I though is was tagged PHP...
Sure narendra,
Replace:
span#metaDetail span#datePosted {
float: left;
margin-left: 30px;
height: 32px;
line-height: 32px;
}
with:
span#metaDetail span#datePosted {
display: none;
}
A while ago i have written a small php script to get the information from MySQL and put it in XML.Now one the description of the item in the MySQL was up untill now something like
<p>
the item description ...etc.</p>
so far so good, i used the following :
preg_match('#<p>(.*?)</p>#s',$stro, $disp);
and that worked fine as expected.
now today the admin has added the new items in the database like this
<p style="font-family: Tahoma; font-size: 13px; line-height: 19.5px;">
item description...etc</p>
and now my "trick" above doesnt work
now i tried (found this on Stackoverflow)
//first line should strip the "style" part to only
$kulaka = preg_replace('/(<[^>]+) style=".*?"/i', '$1', $stro);
// and here we should remove the p tag
preg_match('#<p>(.*?)</p>#s',$kulaka, $disp);
it 'almost' works but it gives me
"style=font-family: Tahoma; font-size: 13px; line-height: 19.5px;> item
desctiption "
any suggestions are welcomed,and i want to do it generally for all styles atributes not only for this particular one, as the Admin can change the size or font etc
This will drop the <p> starting tag (and any attributes within it) as well as the closing tag:
$stro = '<p style="font-family: Tahoma; font-size: 13px; line-height: 19.5px;">'
. 'item description...etc</p>';
preg_match('#^<p.*?>(.*)</p>$#is', $stro, $disp);
echo $disp[1] . PHP_EOL;
Output:
item description...etc
It is not totally solid, as it would fail if there would be any paragraph attribute present with an > in their value, but it may be enough for you in this case.
i'm working on a script that generates multiple CSS into one. And Here is the script.
$full_string = "";
foreach($allfiles as $curfile => $file) {
$file = $PATH[$curfile] . $file;
$file_open = fopen($file , 'r');
$concat = "\n" . fread($file_open , filesize($file)) . "\n";
$full_string .= $concat;
fclose($file_open);
}
return $full_string;
Here i'm combining all the CSS files into one. But the problem now is i have to compare the current CSS($file) with another css(let's consider it as overrider.css). And if $file is having a style like,
h1 {
color: white;
background: teal;
FONT-FAMILY: arial, helvetica, lucida-sans, sans-serif;
FONT-SIZE: 18pt;
FONT-STYLE: normal;
FONT-VARIANT: normal;
}
body
{
font-family: arial;
FONT-SIZE: 14px;
}
and if overrider.css is having a style like,
body
{
font-family: Calibri;
color: #3E83F1;
}
Then final CSS(output.css) generated should be,
h1 {
color: white;
background: teal;
FONT-FAMILY: arial, helvetica, lucida-sans, sans-serif;
FONT-SIZE: 18pt;
FONT-STYLE: normal;
FONT-VARIANT: normal;
}
body
{
font-family: Calibri;
FONT-SIZE: 14px;
color: #3E83F1;
}
Here, since style for body in override.css have font-family, it replaces the font-family property in original CSS and since the color is a new property which is not present in ($file) which is original CSS file, so it should add the property to original CSS file. So how to achieve this in PHP, since i don't have any idea on parsing CSS. Any idea on this would be greatly appreciated.
Please note that i need to generate a new CSS file by giving the input as file1($file) and file2(override.css) and we need to genrate output.css with the styles overridden.
Thanks in advance.
There are a few CSS parsers available (google "php css parser"), like this one that I didn't try, but seems interesting. But personally I'd do the parsing myself - following that kind of pseudo-PHP algorithm
read all the files into one string Str, with all "\n", "\r" and "\t" replaced by a space (to make parsing (a bit) easier)
then, function to process (selector => rules)
func deal with selectors and rules:
rules = array()
do {
S = string from current pos to next `{` excluded (selectors)
R = string from '{' to next '}' (rules)
r = explode(';', R)
lr = make array of rules from r trimmed elements
s = explode (',', S)
ls = make array of [selector => lr]
// same sel: latest rule overwrite existing, added if not exist
merge ls into rules
} while (not '}' and not '#' and not EOF); // the '}' would be the closing media
return rules
Main function to deal with medias, and then call the above function
medias = array();
func deal with Str
do {
if (first non blank char is #) {
media = array of listed medias
eat fist '{'
}
else {
media = array ('GLOBAL')
}
selectorsrules = deal with selectors and rules(rest of Str)
foreach (media as m) {
merge in medias(m) selectorsrules, same procedure as above
}
} while (not EOF);
Interesting project but I don't have the time to implement it fully. Result is in medias array.
if you want font-family: arial; to be apply then add it as font-family: arial !important;
you do not need to worry about merging them because browser will automatically add color to body tag from second css of color found in first css then it will overwrite it with second css.
You have 2 choices:
The simple way is to change your css files and add !important where it is important to be there. It is correct to have for example "body" in css more than 1 time. And whenever you a style to be overridden leave it. Ofcourse this kind of approach is mostly manual. You have to know where it will be overwritten and where not.
The second approach requires string parsing, regular expressions, and i mean you should know your way around the string ad how to parse them. You should get each of the files content, save them to a string, and you should compare them using regex to if a tag is exists in both, then merge the tags content. This way is easy to say but hard to implement.
I have an HTML class that I use to create templates.
My class works like this:
<?php
$page = \TEST\HTML::dispense(':html');
$page->mainWrapper(':div') //creates a child object by using __call() and sets the "div" model
->id('mainWrapper') //sets id
->style('background','red') //adds a style
->text('blah') //adds a text
->addClass('someClass'); //adds a class
->someSpan(':span')
->addClass('spanClass')->addClass('someClass')
->style('font-size','12pt')
->style('border-bottom','1pt dashed black')
->style('background','red');
?>
This allows me for rapid development of html markup without worrying about about a missing character or a misquoted property. Everything gets cached and I have no performance issues.
Now I'd like to take this one step further. In production mode, everything works fine, but for the final output, I'd like to strip out all the inline "style" properties and minimize them and cache them in a css file.
Now, I have a function that loops through all my HTML objects, and aggregates the data according to tag, id, and classes.
My question is: once I have my neat css array in that form:
$style['tag']['.class']['#id']['styleKey'] = styleValue
How do I trim out redundant values so I am left with a relevant css file? Minifying and gzipping can come at a later stage. What I want now is to compare values and optimize the array before dumping it so all 'styleKeys' common to all elements that have the same tag/id/class are grouped together.
So in the example above, for example, since two elements (the div and the span) share the style "background: red" and the class "someClass", I would have a "someClass" CSS rule with "background:red"
If it is of any interest, here is my "extractstyles" function:
<?php
public static function extractStyles($element, array &$styles=array()){
if($element instanceof \TEST\HTML){$element = $element->htmlData();}
$tag = isset($element['#acronym']) ? $element['#acronym'] : NULL;
$id = isset($element['#id']) ? '#'.$element['#id'] : NULL;
$classes = isset($element['#class']) ? $element['#class'] : NULL;
if(isset($element['#style']) && ($tag || $id || $class)){
$ref = &$styles;
if($id){if(!isset($ref[$id])){$ref[$id] = array();};$ref = &$ref[$id];}
if($classes){
if(\is_array($classes)){$classes = '.'.implode('.',$classes);}
if(!isset($ref[$classes])){$ref[$classes] = array();};$ref = &$ref[$classes];
}
if($tag){if(!isset($ref[$tag])){$ref[$tag] = array();};$ref = &$ref[$tag];}
foreach($element[self::ATTRIBUTES]['#style'] as $style=>$value){
$ref[$style] = $value;
}
}
if(isset($element[self::CHILDREN]) && count($element[self::CHILDREN])){
foreach($element[self::CHILDREN] as $child){
self::extractStyles($child, $styles);
}
}
return $styles;
}
?>
Any pointer would be more than welcome...I am really lost. I don't even know if what I am looking for is doable.
As said above, performance is not an issue for now. If it works, I will find a way to optimize it.
Also, please no links to xCSS and other frameworks, as they work on strings and my CSS is created as an array.
Thanks in advance for any help you can give me!
A first order optimization is to Build a hierarchy tree. A parent to child relationship in this tree is a child is a superset of the parent. The root node of this tree is an empty style (which you won't display).
Thus if you had
.parent {
background: red;
}
.childA {
background: red;
border: 1px solid black;
}
.childB {
background: red;
font-weight: 800;
}
The parent is set as the lowest common denominator in the tree. This can then be compressed into 3 classes with less text. The children elements will have all the classes in the path, If you originally had <span class="childA"> you would then get <span class="parent childA">
The compressed classes look like:
.parent {
background: red;
}
.childA {
border: 1px solid black;
}
.childB {
font-weight: 800;
}
A note on IDs, IDs will always be a child of the most appropriate class. Thus if you had
#menu {
background: red;
border: 1px solid black;
margin: 15px 40px;
color: white;
}
It would become the child of ChildA, and its css would be reduced to
#menu {
margin: 15px 40px;
color: white;
}
And displayed as <ul id="menu" class="parent childA">
To create the tree, you will need an object that will store an array of the same children objects (recursively) And a function that when given two objects can determine if their css is a subset, equal or superset, the number of differences, or if there is no commonality.
If you are not familiar with binary search trees, this would be a good time to bone up on that, even though this will be more complex than that, it will be a good start in the right direction.
A second order optimization is determining if nesting of child elements can further reduce the need of classes. For example if all your <li> inside <ul id="#menu"> were styled similarly it would make sense that you could create a rule for #menu li
To do this, you need to go to each node, and analyze its children. If all the children of the same node type share a common style element (use the set comparer above), extract the common set element as a parent. The differences become the children.
Lets say you have this as an example (note is has already gone through pass 1):
<ul id="menu" class="parent childA">
<li class="top menuli">Item</li>
<li class="menuli">Item</li>
<li class="menuli">Item</li>
<li class="menuli">Item</li>
<li class="bottom menuli">Item</li>
</ul>
We note that all the <li> have a common element .menuli, this means we can eliminate this class that was created in pass 1 and replace it with a flat rule of #menu li. We do this by removing the menuli class from each child li, and replacing the .menuli rule with the #menu li rule.
Our css changes like from:
#menu {
margin: 15px 40px;
color: white;
}
.menuli {
font-size: 30px;
font-weight: 800;
margin: 8px 0;
}
to
#menu {
margin: 15px 40px;
color: white;
}
#menu li {
font-size: 30px;
font-weight: 800;
margin: 8px 0;
}
And the html looses the class menuli
<ul id="menu" class="parent childA">
<li class="top">Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li class="bottom">Item</li>
</ul>
Remember to use a breadth first search when searching down your node tree instead of depth first search. If you are aggressive, you can keep checking 2nd levels for similar tags across many paths, a common 2nd level search might reveal similar classes for #menu li a or #container div p etc. This becomes an NP hard problem if you allow unlimited depth searching.
Hope this helps. If this is the direction you want to go, I'd be happy to help with more code concerning the set comparator and possibly the tree searcher, although that is significantly more complex.