Two Columns - One Ordered List Jekyll - html-lists

How can I adapt my current two-column (using Bootstrap) ordered list in a Jekyll site? The goal is to have Jekyll take my .md file, of ordered list items and split it into two columns. I currently have to individually edit each ordered list in the two columns which will be problematic in the long run, as this document is updated and added to constantly.
Here is my current code:
<!-- Left Column -->
<div class="col-sm">
<ol>
<li>Zebras</li>
<li>Lions</li>
</ol>
</div>
<!-- Right Column -->
<div class="col-sm">
<ol start="3">
<li>Zebras</li>
<li>Lions</li>
</ol>
</div>
Here is a visual of what I would like to accomplish via Jekyll.
Input (Markdown file):
---
layout: default
---
1. Zebras
2. Lions
3. Tigers
4. Gorillas
Ideally, this would then be parsed into:
1. Zebras 3. Tigers
2. Lions 4. Gorillas
I found two on-topic StackOverflow questions, however, neither fit this use case. The first uses YAML front-matter to build the list. However, since I often have links in my ordered list, I do not think this method would work—also, would be equally as tedious as adding each list item. The second gets closer, however, I think it is using the post files whereas I am using list items.
Can I have Jekyll take the number of ordered list items, split those in half (or if not exact, the left column should be greater than the right), then put the list items in their respective columns? Finally, carrying over the counter from the left column (either using <ol start="x"> or something else).

Here's an idea: Use one column and add style="column-count: 2" to that. Done!
More css column options: https://css-tricks.com/almanac/properties/c/columns/#article-header-id-0

You can try to use Cards columns from Bootstrap. By default, they are 3 columns, but you can modify the default value.
Check this link: https://getbootstrap.com/docs/4.0/components/card/#card-columns

Related

Xpath syntax to grab listed elements based on ID above containing word

I want to grab li element text and links from a list. The challenge is, the span sometimes has different class names BUT always has the word 'notable' featured in them, example:
<span class="mw-headline" id="Notable_alumni">Notable alumni</span>
OR
<span class="mw-headline" id="Notable_former_pupils">Notable former pupils</span>
So I need to use "contains" somehow, so I am along these lines:
//li[contains(span/#id,'Notable')]/span/#id/following-sibling::text()
But can't get this right.
Another issue is these blocks of text and headers are not in the same containing div either. Added an image to simplify and you can see the code.
Assuming that the span with the #id is always under the h2 (you could make more generic by using * instead of h2 if that doesn't hold true). If you anchor to that containing element, then look for the first ul that is a following-sibling, you can select the text() from all of it's li elements:
//h2[span[contains(#id,'Movie Title')]]/following-sibling::ul[1]/li//text()

Selecting text from multiple paragraphs using xpath

I have a situation where my end points and mid points can vary.
I always have:
<p style="margin-top: 0px;" >
and
<p class="contactAdvisor">
in between, I will have varying items including <b>, <i>, <strong>, <br> headings 1,2 or 3. I might also have one or more <p> in between the two fixed items.
What I'm trying to get is all of the text in between these two elements no matter whether wrapped in headings, various stylings or inside sub paragraph elements.
I've messed around with contains and preceding/following-sibling but my best attempt has been to create based on pre/follow for each use case. And even that leaves me with some issues because if there are multiple <p> inside and I'm trying to select all of them, I only get one.
Depending on the hierarchy, you can use either preceding:: or preceding-sibling::.
Try selectong something along the lines of:
//*[preceding::p[#style="margin-top: 0px;"] and not (preceding::p[#class="contactAdvisor"])]
This should exclude everything before the first p with the first condition and everything after the second with the second. Untested so you may have to tweak the check a little.
//p[#style="margin-top: 0px;"]/following::*[following::p[#class="contactAdvisor"]]
//*[preceding::p[#style="margin-top: 0px;"] and following::p[#class="contactAdvisor"]]

How get AJAX elements which XPATH is varying dynamically

In my application one AJAX filed which is displaying some values
When I tried to find out their XPATH it is varying dynamically
for example :
First time when I tried to find out the path it is giving it as .//*[#id='ix-rt-13']. When I refresh the page it is giving it as .//*[#id='ix-rt-6'].
Actually it is displaying 2 values one with id .//*[#id='ix-rt-13'] and second one with .//*[#id='ix-rt-14']. And when I refresh the page it is giving XPath values as .//*[#id='ix-rt-6'] and .//*[#id='ix-rt-7'].
I want to retrieve the second element text. How to do that ?
<li class="ui-menu-item" role="presentation">
<a id="'ix-rt-15" class="ui-corner-all ui-state-focus" tabindex="-1">Being Powerful</a>
</li>
If I understand the question correctly, you can try this XPath :
(//*[starts-with(#id,'ix-rt-')])[2]
Above XPath will search for all elements with id attribute value starts with 'ix-rt-', then return the 2nd result.
If link text does not change, you shouldn't use xpath rather use link text:
driver.findElement(By.linkText("Being Powerful")).click();
However if you bend upon using xpath you may try following:
driver.findElement(By.xpath("//a[contains(#id,'ix-rt-')]")).click();
But this would select the 1st element containing 'ix-rt-' in its id. So it may not work as desired if there are more than 1 such elements. In that case, if you know the index of element on page, you may use following:
driver.findElement(By.xpath("(//a[contains(#id,'ix-rt-')])[2]")).click();

Xpath - Extracting multiple specific differnt parts of text strings from one text node

I have three samples of text nodes that and I want to extract three different parts of the text, using a universal x-path.
First
<p class="product-summary">
This is an amazing game from the company Midway Games. Excellent gameplay. Very good game.
</p>
Second
<p class="product-summary">
New Line Cinema distributed this movie in 1995.
</p>
Third
<p class="product-summary">
New game from 2011, with new 3D graphics. This game was made by NetherRealm Studios.
</p>
The extraction should be either Midway Games or New Line Cinema or NetherRealm Studios
Note that the text node allways include just one company, never two or three (just one).
My try is from this question but the problem is that it dosen't work nor include all three companies.
substring('Midway Games',1,12*contains(//p[#class='product-summary']/following-sibling::text()[1], 'Midway Games'))
As the input will only contain one of them, you can use concat to join the results.
concat(
substring('Midway Games', 1,
12*contains(//p[#class='product-summary'], 'Midway Games')),
substring('Line Cinema', 1,
11*contains(//p[#class='product-summary'], 'Line Cinema')),
substring('NetherRealm Studios', 1,
19*contains(//p[#class='product-summary'], 'NetherRealm Studios'))
)
You can remove the line breaks that I added for readability as you want.
I had to fix the query you provided: the text nodes are no following-siblings, but children. Your XPath processor will query the (concatenated) text nodes below that element anyway as contains works on strings.

How to find the first link on the page containing this text?

If I have two links:
<div class="abc">
<a id="def1" href="/definitely">Definitely 1</a>
<a id="def2" href="/definitely">Definitely 2</a>
</div>
And I want to identify the first (def1), I thought this would work:
var linkXPath = "//div[#class='abc']//a[contains(#href,'def')][1]";
But it doesn't seem to.
What am I doing wrong?
It is a FAQ why
//someName[1]
doesn't select the first element of //someName.
Looking at the definition of the // abbreviation, one would realize that in fact
//someName[1]
is equivalent to:
/descendant-or-self::node()/someName[1]
and this selects every someName element that is the first someName child of its parent node.
Thus, if there are two or more someName elements that are the first someName child of their parent, all of them are selected.
Solution:
Instead of
//someName[1]
use:
(//someName)[1]
So, in your particular case use:
(//div[#class='abc']//a[contains(#href,'def')]) [1]
Apart from this, none of the above expressions would select any node, if in the actual XML document a default namespace was specified. Selecting nodes in a document with a default namespace is the biggest XPath FAQ. To find the solution just search for "default namespace" in this SO tag and anywhere on the Internet.
Your XPath expression selects the first a element (with the right href) of every div (that has the right class) that contains one. So if there were two divs that matched, each with multiple a elements that matched, you'd get a reault set containing two elements -- the first a in the first div, and the first a in the second div.
To select just the first element of the entire result set, use parentheses like so:
(//div[#class='abc']//a[contains(#href,'def')])[1]
Other than that, your expression works fine for me (tested here).

Resources