65.9K
CodeProject is changing. Read more.
Home

Adapting GRML

starIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIconemptyStarIcon

1.55/5 (8 votes)

Sep 3, 2004

6 min read

viewsIcon

97364

downloadIcon

177

Convert a HTML web page to GRML.

Introduction

This article introduces the process of adapting (or converting) a web page from one markup language to another. It discusses how to adapt a HTML web page to GRML. Two examples are provided. The first demonstrates how to extract hyperlinks from an HTML web page and convert it to GRML. The second demonstrates how to do this with images. These examples require server-side processing. Here, IIS, Active Server Pages (ASP), and PERL are used.

Background

It is recommended to have some experience with ASP and PERL. PERL has regular expression support that is used to extract the hyperlinks and images from the web page. Any server-side scripting environment does this, including .NET, CGI, or PHP. However, PERL and ASP are used for this article. While PERL is required, the server-side scripting language specifically used is PerlScript. To use PerlScript, download a PERL interpreter. To get one that works with IIS, try ActivePerl. If not done already, read Introducing GRML and Using GRML. These articles provide explanations of what GRML is and how it is used.

What is an Adapter?

An adapter is generally defined as...

an object that converts the original interface of a component to another interface.

For the purposes of this article, the definition of an adapter is...

server-side processing or scripting that converts one markup language to another.

This definition describes converting HTML to GRML using ASP. The adapter object is the ASP scripting, the original interface is HTML, and the other interface is GRML.

Depending on what is being converted, adapters need to read from the original interface and write to the other interface. In other words, an adapter needs an interface reader and an interface writer. A HTML to GRML adapter requires a HTML reader and a GRML writer.

Adapting hyperlinks and images

HTML does not describe many elements of its content. For example, there is no way to determine the attributes of one text block from another. However, not all HTML content is without description. It does have specific tags for hyperlinks and images.

Using a specific tag to identify content makes it possible to create a script that reads only those tags. When found, the unwanted tag elements are removed, leaving only the content. The script then writes the content in the new format or markup language. This is how it adapts HTML hyperlinks or images to GRML.

The Hyperlink adapter

The use of the <a href=> tag allows a HTML web browser to identify which text is a hyperlink. This tag is the basis for the hyperlink adapter. It extracts all hyperlinks from an HTML web page and converts them to GRML.

Below is an example of a HTML to GRML hyperlinks adapter, using PerlScript:

<%@ Language="PerlScript%">
<HTML>
<center>
<form action=links.asp>
URL to extract: <input type=text name=url1 length=60>
<input type=submit>
</form>
</center>
<!--
<grml>
<edit url1>
<title>Enter URL:>
<%
use HTML::LinkExtor;
use URI::URL;
use LWP;

my $url, $html;

# Parsing the Request
$url = $Request->QueryString("url1")->Item();

$Response->Write("<submit>\n");
$Response->Write("<location>GRMLBrowser.com/links.asp\n");
$Response->Write("</submit>\n");
$Response->Write("<edit url1>\n");
$Response->Write("<text>$url\n");
$Response->Write("</edit>\n");

if ($url eq "")
{
        $Response->Write("</GRML>\n");
}
else
{
        if ($url !~ /http:\/\//)
        {
            $url = "http://". $url;
        }
}

# Constructing the Request
    $_ = $sites;

# Retrieving the Response/Resultset
#    - Filtering the Resultset (optional)
my $ua = LWP::UserAgent->new(agent => "Mozilla 4.0");
my $request  = HTTP::Request->new('GET', $url);
my $response = $ua->request($request);

unless ($response->is_success)
{
    print $response->error_as_HTML . "\n";
    exit(1);
}

my $res = $response->content(); # content without HTTP header

$Response->Write("<column>\n");
$Response->Write("<Title>\n");
$Response->Write("<Request>\n");
$Response->Write("<link>\n");
$Response->Write("</column>\n");

$Response->Write("<result>\n");

$res =~ s/\n/ /gsi;

while($res =~ m|href=(.+?)>(.*?)</A>|gsi)   ## that's all ...
{
    my $temp_link = $1;
    my $temp_item = $2;
    
    $temp_link =~ s/\'//gsi;
    $temp_link =~ s/\"//gsi;
    $temp_link =~ s/ (.*)//gsi;
    $temp_link =~ s/<b>//gsi;
    $temp_link =~ s/<\/b>//gsi;
    $temp_link =~ s/&amp;/\&/gsi;
    $temp_link =~ s/\n(.*)//gsi;
    $temp_item =~ s/<b>//gsi;
    $temp_item =~ s/<\/b>//gsi;
    $temp_item =~ s/<(.+?)>//gsi;
    $temp_item =~ s/<\/font>//gsi;
    $temp_item =~ s/&amp;/\&/gsi;
    $temp_item =~ s/ / /gsi;
    $temp_item =~ s/&quot;/\"/gsi;
    $temp_item =~ s/\n(.*)//gsi;
    $temp_item =~ s/\n/  /gsi;
    $temp_item =~ s/  (.*)//gsi;
    $temp_item =~ s/   (.*)//gsi;
   

    if ($temp_item !~ /img src=/)
    {
        if ($temp_link !~ /$url/ && $temp_link !~ /\/\//)
        {
            $temp_link = $url . "\/" . $temp_link;
        }

        $temp_item =~ s/\n//gsi;
        $temp_link =~ s/\n//gsi;

        $Response->Write("<link>$temp_link\n");
        $Response->Write("<title>$temp_item\n");    
    }

    $Response->Write("<request>$url\n");
    $Response->Write("\n\n");
}

$Response->Write("</result>\n");
$Response->Write("</GRML>\n");
%>
-->
</html>

What the above code does is it creates a form in HTML that extracts all the hyperlinks from a web page. The hyperlinks (and their titles) are formatted using GRML. To view GRML, a GRML web browser is required (such as Pioneer Report MDI).

All of the server-side scripting is used as the HTML reader. Only the following lines are used as the GRML writer. They are:

  • $Response->Write("\n");
  • $Response->Write("\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("<Request>\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("<link>\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("</column>\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("<result>\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("<link>$temp_link\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("<title>$temp_item\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("<request>$url\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("</result>\n");</CODE> </LI></UL> <P>Only the last three lines format the hyperlinks using GRML. The first two lines create the form in the browser window of a GRML web browser and do not use the adapted HTML hyperlinks.</P> <P>To see the above in action, go to <A href="http://grmlbrowser.com/links.asp" target=_blank>Hyperlink adapter</A> or copy the above script to a file and host it from a local web server. Once the web page is displayed, enter a URL and press the 'Submit' button. It displays all the hyperlinks extracted from the HTML web page formatted in GRML.</P> <P>After adapting hyperlinks from HTML to GRML, this is how it appears in a GRML web browser (using Pioneer Report MDI):</P> <P><IMG height=351 src="adaptingGRML/PRM1_001.jpg" width=425></P> <H2>The Image adapter</H2> <P>Using the <CODE lang=html><span class="code-keyword"><</span><span class="code-leadattribute">img</span> <span class="code-attribute">src</span><span class="code-keyword">=</span><span class="code-keyword">></span></CODE> tag, a script is able to find and extract images from HTML. By reading this tag and removing unwanted tag elements, the HTML images are converted to GRML. The following script demonstrates this:</P><PRE lang=perlscript><span class="code-pagedirective"><%@</span><span class="code-leadattribute"> Language</span><span class="code-keyword">="</span><span class="code-keyword">PerlScript%"</span><span class="code-attribute">> <center> <form action</span><span class="code-keyword">=translate.asp</span><span class="code-attribute">> URL to translate: <input type</span><span class="code-keyword">=text</span><span class="code-attribute"> name</span><span class="code-keyword">=url1</span><span class="code-attribute"> length</span><span class="code-keyword">=60</span><span class="code-attribute">> <input type</span><span class="code-keyword">=submit</span><span class="code-attribute">> </form> </center> <!-- <grml> <edit url1> <title>Enter URL: </edit> <% use HTML::LinkExtor; use URI::URL; use LWP; my $url, $html; # Parsing the Request $url </span><span class="code-keyword">=</span><span class="code-attribute"> $Request->QueryString("url1")->Item(); if ($url eq "") { $Response->Write("</GRML>\n"); } else { if ($url !~ /http:\/\//) { $url </span><span class="code-keyword">= "</span><span class="code-keyword">http://"</span><span class="code-attribute"> . $url; } } $Response->Write("### URL ###\n\n"); $Response->Write("The url is: $url\n\n"); # Constructing the Request $_ </span><span class="code-keyword">=</span><span class="code-attribute"> $sites; # Retrieving the Response/Results # - Filtering the Results (optional) my $ua </span><span class="code-keyword">=</span><span class="code-attribute"> LWP::UserAgent->new(agent </span><span class="code-keyword">=</span><span class="code-attribute">> "my agent V1.00"); my $request </span><span class="code-keyword">=</span><span class="code-attribute"> HTTP::Request->new('GET', $url); my $response </span><span class="code-keyword">=</span><span class="code-attribute"> $ua->request($request); unless ($response->is_success) { print $response->error_as_HTML . "\n"; exit(1); } my $res </span><span class="code-keyword">=</span><span class="code-attribute"> $response->content(); # content without HTTP header my @imgs </span><span class="code-keyword">=</span><span class="code-attribute"> (); my @hrefs </span><span class="code-keyword">=</span><span class="code-attribute"> (); # Make the parser. Unfortunately, we don't know the base yet # (it might be diffent from $url) my $p </span><span class="code-keyword">=</span><span class="code-attribute"> HTML::LinkExtor->new(\&callback); $p->parse($res); # Expand all image URLs to absolute ones my $base </span><span class="code-keyword">=</span><span class="code-attribute"> $response->base; @imgs </span><span class="code-keyword">=</span><span class="code-attribute"> map { $_ </span><span class="code-keyword">=</span><span class="code-attribute"> url($_, $base)->abs; } @imgs; $Response->Write("<column>\n"); $Response->Write("<image>\n"); $Response->Write("<link>\n"); $Response->Write("</column>\n\n"); $Response->Write("<result>\n"); foreach (@imgs) { $Response->Write("<image>$_\n"); } $Response->Write("\nLinks:\n"); foreach (@hrefs) { my $temp </span><span class="code-keyword">=</span><span class="code-attribute"> $_; if ($temp !~ /$url/ && $temp !~ /\/\//) { $temp </span><span class="code-keyword">=</span><span class="code-attribute"> $url . "\/" . $temp; } $Response->Write("<link>$temp\n"); } sub callback { my($tag, %attr) </span><span class="code-keyword">=</span><span class="code-attribute"> @_; push(@imgs , values %attr) if $tag eq 'img'; push(@hrefs, values %attr) if $tag eq 'a'; } </span><span class="code-pagedirective">%></span> <span class="code-keyword"><</span><span class="code-keyword">/</span><span class="code-leadattribute">result</span><span class="code-keyword">></span> <span class="code-keyword"><</span><span class="code-keyword">/</span><span class="code-leadattribute">GRML</span><span class="code-keyword">></span> --></PRE> <P>The above script is used as an HTML reader, except for the lines used to build the columns and each result. These lines are the GRML writer:</P> <UL> <LI><CODE lang=perlscript>$Response->Write("<column>\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("<image>\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("<link>\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("</column>\n\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("<result>\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("<image>$_\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("<link>$temp\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("</result>\n");</CODE> </LI></UL> <P>Once the image content has been adapted to GRML, this is how it looks in a GRML web browser (using Pioneer Report MDI):</P> <P><IMG height=351 src="adaptingGRML/PRM1_002.jpg" width=425></P> <H2>Conclusion</H2> <P>Converting HTML to GRML is possible when using an adapter. Only the content with identifiable tags are adaptable from one markup language to another. In the case of HTML, there are tags to identify hyperlinks and images.</P> <P>The examples described for adapting content show how to convert HTML hyperlinks or images to GRML. The adapter consists of a HTML reader and a GRML writer. Using this adapter, a web page viewed with a HTML web browser is viewable using a GRML web browser.</P> <H2>Latest changes</H2> <UL> <LI>09/03/04 <UL> <LI>Using GRML v1.2 in code samples. </LI></UL> <LI>10/08/04 <UL> <LI>Using GRML v2.3 in code samples. Pioneer Report MDI 3.64 uses GRML v1.2 while all other GRML web browsers use v2.3. </LI></UL></LI></UL> </div></div></div></div><div><div id="div-gpt-ad-1738591766860-0" style="min-width:300px;min-height:600px" class="mt-40 sticky top-40"></div></div></div><!--$--><!--/$--><!--$--><!--/$--></main><footer class="custom-container flex flex-col gap-3 px-2"><div class="mt-2 py-4 min-h-36 bg-primary"></div><div class="border-t-4 border-primary p-3 flex justify-between"><nav class="flex-1"><ul><li><a href="http://developermedia.com/" rel="nofollow noreferrer">Advertise</a></li><li><a href="/info/privacy.aspx">Privacy</a></li><li><a href="/info/cookie.aspx">Cookies</a></li><li><a href="/info/TermsOfUse.aspx">Terms of Use</a></li></ul></nav><div class="flex-1"></div><div class="flex-1 text-gray text-sm text-right">Copyright © <a href="mailto:webmaster@codeproject.com">CodeProject</a>, 1999-2025<br/>All Rights Reserved.</div></div></footer><script src="/_next/static/chunks/webpack-5ed466aeca77ac7a.js" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[387,[\"869\",\"static/chunks/869-095b567be01917e3.js\",\"177\",\"static/chunks/app/layout-12dfdcc6fc1e5fcf.js\"],\"default\"]\n3:I[6874,[\"869\",\"static/chunks/869-095b567be01917e3.js\",\"76\",\"static/chunks/app/(article)/Articles/%5BarticleId%5D/%5BarticleSlug%5D/page-ade9d0789736a960.js\"],\"\"]\n4:I[3063,[\"869\",\"static/chunks/869-095b567be01917e3.js\",\"76\",\"static/chunks/app/(article)/Articles/%5BarticleId%5D/%5BarticleSlug%5D/page-ade9d0789736a960.js\"],\"Image\"]\n5:I[6932,[\"869\",\"static/chunks/869-095b567be01917e3.js\",\"76\",\"static/chunks/app/(article)/Articles/%5BarticleId%5D/%5BarticleSlug%5D/page-ade9d0789736a960.js\"],\"default\"]\n6:I[7231,[\"869\",\"static/chunks/869-095b567be01917e3.js\",\"177\",\"static/chunks/app/layout-12dfdcc6fc1e5fcf.js\"],\"default\"]\n7:I[7555,[],\"\"]\n8:I[1295,[],\"\"]\na:I[9665,[],\"MetadataBoundary\"]\nc:I[9665,[],\"OutletBoundary\"]\nf:I[4911,[],\"AsyncMetadataOutlet\"]\n11:I[9665,[],\"ViewportBoundary\"]\n13:I[6614,[],\"\"]\n14:\"$Sreact.suspense\"\n15:I[4911,[],\"AsyncMetadata\"]\n:HL[\"/_next/static/media/945b7384c5256ec3-s.p.ttf\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/ttf\"}]\n:HL[\"/_next/static/media/b55e164a6e7ce445-s.p.ttf\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/ttf\"}]\n:HL[\"/_next/static/media/e337cf18f0f81cb9-s.p.ttf\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/ttf\"}]\n:HL[\"/_next/static/media/f7794ce32483498f-s.p.ttf\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/ttf\"}]\n:HL[\"/_next/static/css/f00fbee724adea66.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"w45CmwcSwIZhM0-Q0VqIS\",\"p\":\"\",\"c\":[\"\",\"Articles\",\"8170\",\"Adapting-GRML\"],\"i\":false,\"f\":[[[\"\",{\"children\":[\"(article)\",{\"children\":[\"Articles\",{\"children\":[[\"articleId\",\"8170\",\"d\"],{\"children\":[[\"articleSlug\",\"Adapting-GRML\",\"d\"],{\"children\":[\"__PAGE__\",{}]}]}]}]}]},\"$undefined\",\"$undefined\",true],[\"\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/f00fbee724adea66.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[[\"$\",\"head\",null,{\"children\":[[\"$\",\"link\",null,{\"rel\":\"apple-touch-icon\",\"sizes\":\"144x144\",\"href\":\"/favicon/apple-touch-icon.png\"}],[\"$\",\"link\",null,{\"rel\":\"icon\",\"type\":\"image/png\",\"sizes\":\"32x32\",\"href\":\"/favicon/favicon-32x32.png\"}],[\"$\",\"link\",null,{\"rel\":\"icon\",\"type\":\"image/png\",\"sizes\":\"16x16\",\"href\":\"/favicon/favicon-16x16.png\"}],[\"$\",\"link\",null,{\"rel\":\"manifest\",\"href\":\"/favicon/manifest.json\"}],[\"$\",\"link\",null,{\"rel\":\"mask-icon\",\"href\":\"/favicon/safari-pinned-tab.svg\",\"color\":\"#ff9900\"}],[\"$\",\"meta\",null,{\"property\":\"og:title\",\"content\":\"CodeProject\"}],[\"$\",\"meta\",null,{\"property\":\"og:image\",\"content\":\"https://www.codeproject.com/favicon/mstile-150x150.png\"}],[\"$\",\"meta\",null,{\"property\":\"og:description\",\"content\":\"For those who code\"}],[\"$\",\"meta\",null,{\"property\":\"og:url\",\"content\":\"https://www.codeproject.com\"}],[\"$\",\"script\",null,{\"async\":true,\"src\":\"https://securepubads.g.doubleclick.net/tag/js/gpt.js\"}],[\"$\",\"$L2\",null,{}]]}],[\"$\",\"body\",null,{\"className\":\"__className_2277ee\",\"children\":[[\"$\",\"header\",null,{\"children\":[[\"$\",\"div\",null,{\"className\":\"custom-container gap-2 py-1 text-gray-light flex justify-between whitespace-nowrap z-10 relative px-1 md:px-0\",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex-1 md:ml-20\",\"children\":[[\"$\",\"span\",null,{\"className\":\"hidden md:block\",\"children\":[65.938,\" articles\"]}],[\"$\",\"span\",null,{\"className\":\"block md:hidden\",\"children\":[\"65.9\",\"K\"]}]]}],[\"$\",\"div\",null,{\"className\":\"flex-1\",\"children\":[\"CodeProject is changing.\",\" \",[\"$\",\"$L3\",null,{\"href\":\"/info/Changes.aspx\",\"className\":\"!text-gray-lightest\",\"children\":\"Read more.\"}]]}],[\"$\",\"div\",null,{\"className\":\"flex-1\"}],[\"$\",\"div\",null,{\"className\":\"flex-1\"}]]}],[\"$\",\"div\",null,{\"className\":\"mb-2 mt-2 md:mt-0\",\"children\":[\"$\",\"div\",null,{\"className\":\"h-[94px] bg-primary\",\"children\":[\"$\",\"div\",null,{\"className\":\"custom-container relative h-full\",\"children\":[[\"$\",\"$L3\",null,{\"href\":\"/\",\"children\":[\"$\",\"$L4\",null,{\"className\":\"absolute -top-[31px]\",\"src\":\"/logo250x135.gif\",\"priority\":true,\"alt\":\"Home\",\"width\":250,\"height\":135}]}],[\"$\",\"div\",null,{\"className\":\"w-[calc(100%-300px)] translate-x-[300px] translate-y-[2px] h-[90px] relative overflow-hidden\",\"children\":[\"$\",\"$L5\",null,{\"adUnit\":\"/67541884/CPLeader728\",\"adSlotId\":\"div-gpt-ad-1738591571151-0\",\"adSize\":[728,90],\"className\":\"absolute top-0 left-0\"}]}]]}]}]}],[\"$\",\"$L6\",null,{}]]}],[\"$\",\"main\",null,{\"className\":\"px-2 py-10\",\"children\":[\"$\",\"$L7\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L8\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}],[\"$\",\"footer\",null,{\"className\":\"custom-container flex flex-col gap-3 px-2\",\"children\":[[\"$\",\"div\",null,{\"className\":\"mt-2 py-4 min-h-36 bg-primary\"}],[\"$\",\"div\",null,{\"className\":\"border-t-4 border-primary p-3 flex justify-between\",\"children\":[[\"$\",\"nav\",null,{\"className\":\"flex-1\",\"children\":[\"$\",\"ul\",null,{\"children\":[[\"$\",\"li\",null,{\"children\":[\"$\",\"a\",null,{\"href\":\"http://developermedia.com/\",\"rel\":\"nofollow noreferrer\",\"children\":\"Advertise\"}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"$L3\",null,{\"href\":\"/info/privacy.aspx\",\"children\":\"Privacy\"}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"$L3\",null,{\"href\":\"/info/cookie.aspx\",\"children\":\"Cookies\"}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"$L3\",null,{\"href\":\"/info/TermsOfUse.aspx\",\"children\":\"Terms of Use\"}]}]]}]}],[\"$\",\"div\",null,{\"className\":\"flex-1\"}],[\"$\",\"div\",null,{\"className\":\"flex-1 text-gray text-sm text-right\",\"children\":[\"Copyright © \",[\"$\",\"a\",null,{\"href\":\"mailto:webmaster@codeproject.com\",\"children\":\"CodeProject\"}],\", 1999-2025\",[\"$\",\"br\",null,{}],\"All Rights Reserved.\"]}]]}]]}]]}]]}]]}],{\"children\":[\"(article)\",[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L7\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L8\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:1:props:children:1:props:children:1:props:children:1:props:children:props:notFound:0:1:props:style\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":\"$0:f:0:1:1:props:children:1:props:children:1:props:children:1:props:children:props:notFound:0:1:props:children:props:children:1:props:style\",\"children\":404}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:1:props:children:1:props:children:1:props:children:1:props:children:props:notFound:0:1:props:children:props:children:2:props:style\",\"children\":[\"$\",\"h2\",null,{\"style\":\"$0:f:0:1:1:props:children:1:props:children:1:props:children:1:props:children:props:notFound:0:1:props:children:props:children:2:props:children:props:style\",\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[\"Articles\",[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L7\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L8\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"articleId\",\"8170\",\"d\"],[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L7\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L8\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"articleSlug\",\"Adapting-GRML\",\"d\"],[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L7\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L8\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[\"__PAGE__\",[\"$\",\"$1\",\"c\",{\"children\":[\"$L9\",[\"$\",\"$La\",null,{\"children\":\"$Lb\"}],null,[\"$\",\"$Lc\",null,{\"children\":[\"$Ld\",\"$Le\",[\"$\",\"$Lf\",null,{\"promise\":\"$@10\"}]]}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false]},null,false],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$1\",\"QZAMbal-CzgrSn3jDwfNj\",{\"children\":[[\"$\",\"$L11\",null,{\"children\":\"$L12\"}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],null]}],false]],\"m\":\"$undefined\",\"G\":[\"$13\",\"$undefined\"],\"s\":false,\"S\":false}\n"])</script><script>self.__next_f.push([1,"b:[\"$\",\"$14\",null,{\"fallback\":null,\"children\":[\"$\",\"$L15\",null,{\"promise\":\"$@16\"}]}]\ne:null\n12:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\nd:null\n"])</script><script>self.__next_f.push([1,"16:{\"metadata\":[[\"$\",\"title\",\"0\",{\"children\":\"Adapting GRML - CodeProject\"}],[\"$\",\"link\",\"1\",{\"rel\":\"manifest\",\"href\":\"/manifest.json\",\"crossOrigin\":\"$undefined\"}]],\"error\":null,\"digest\":\"$undefined\"}\n10:{\"metadata\":\"$16:metadata\",\"error\":null,\"digest\":\"$undefined\"}\n"])</script><script>self.__next_f.push([1,"17:I[9741,[\"869\",\"static/chunks/869-095b567be01917e3.js\",\"76\",\"static/chunks/app/(article)/Articles/%5BarticleId%5D/%5BarticleSlug%5D/page-ade9d0789736a960.js\"],\"default\"]\n19:I[6947,[\"869\",\"static/chunks/869-095b567be01917e3.js\",\"76\",\"static/chunks/app/(article)/Articles/%5BarticleId%5D/%5BarticleSlug%5D/page-ade9d0789736a960.js\"],\"default\"]\n18:T706f,"])</script><script>self.__next_f.push([1,"/*\n This is the legacy article critical styles\n They are added in order to reduce mvp development time\n They should be refactored or completely replaced woth nextjs css modules in future\n*/\n\n::selection {\n background-color: #f90;\n color: #fff;\n text-shadow: none;\n}\n.blank-background {\n background-color: white;\n}\nhtml,\ndiv,\nspan,\napplet,\nobject,\niframe,\na,\nabbr,\nacronym,\nbig,\ncite,\ncode,\ndel,\ndfn,\nem,\nfont,\nimg,\nins,\nkbd,\nq,\ns,\nsamp,\nsmall,\nstrike,\nstrong,\nsub,\nsup,\ntt,\nvar,\nfieldset,\nform,\nlabel,\ntable,\ntbody,\ntfoot,\nthead,\ntr,\nth,\ntd,\nli,\nol,\nul {\n margin: 0;\n padding: 0;\n border: 0;\n}\nhtml {\n font-size: 16px;\n -webkit-font-smoothing: antialiased;\n font-smooth: always;\n}\nbody,\np,\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\nli,\ntr,\ntd,\nth,\ndd,\ndt {\n font-size: 16px;\n line-height: 1.4;\n color: #111111;\n}\nbody {\n margin: 0;\n}\nh1,\nh3,\nh4,\nh5,\nth {\n font-weight: bold;\n}\nh1 {\n color: #333333;\n padding: 0px;\n margin: 0 0 7px;\n text-align: left;\n}\nh2 {\n margin: 20px 0 11px;\n padding: 0;\n padding-bottom: 10px;\n color: #333333;\n}\nh3 {\n color: #ff9900;\n}\nh1 {\n font-size: 38px;\n font-weight: 400;\n}\nh2 {\n font-size: 29px;\n font-weight: 400;\n}\nh3 {\n font-size: 19px;\n font-weight: normal;\n}\nh4 {\n font-size: 17px;\n}\npre {\n color: black;\n background-color: #fbedbb;\n padding: 6px;\n font: 14px Consolas, monospace, mono;\n white-space: pre;\n overflow: auto;\n border: solid 1px #fbedbb;\n -moz-tab-size: 4;\n -o-tab-size: 4;\n -webkit-tab-size: 4;\n tab-size: 4;\n}\ncode {\n color: #990000;\n font: 15px Consolas, monospace, mono;\n}\ntable {\n background-color: Transparent;\n}\nimg {\n -ms-interpolation-mode: bicubic;\n}\na {\n text-decoration: none;\n color: #005782;\n}\na:visited {\n color: #800080;\n}\na:hover {\n text-decoration: underline;\n}\na:not([href]) {\n color: inherit;\n text-decoration: none;\n}\ninput[type=\"text\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"email\"],\ninput[type=\"number\"],\ninput[type=\"password\"],\nselect,\ntextarea {\n border: 1px solid #d7d7d7;\n font-size: 16px;\n padding: 5px;\n}\na.button,\na.button-large,\n.button,\n.button-large {\n color: white;\n background-color: #e08900;\n border: 1px solid #cccccc;\n text-decoration: none;\n white-space: nowrap;\n font-size: 100%;\n padding: 4px;\n cursor: pointer;\n border-radius: 3px;\n -webkit-border-radius: 3px;\n -moz-border-radius: 3px;\n}\ntable.small-text td,\nul.small-text li,\nol.small-text li,\n.small-text {\n font-size: 14px;\n}\n.invisible {\n display: none;\n}\n.subdue,\n.subdue li,\ntr.subdue td {\n color: #808080;\n}\n.bold {\n font-weight: bold;\n}\n.align-left {\n text-align: left;\n}\n.align-right {\n text-align: right;\n}\n.align-center {\n text-align: center;\n}\n.float-right {\n float: right;\n}\n.float-left {\n float: left;\n}\n.sticky {\n position: sticky;\n top: 0;\n}\n.extended {\n width: 100%;\n box-sizing: border-box;\n}\n.padded-top {\n padding-top: 20px;\n}\n.tight {\n margin: 0px;\n padding: 0px;\n}\n.nowrap {\n white-space: nowrap;\n}\n.fixed-layout {\n table-layout: fixed;\n}\n.clip-text {\n text-overflow: ellipsis;\n overflow: hidden;\n white-space: nowrap;\n}\n.raised {\n background-color: #fff8df;\n border: 1px solid #cccccc;\n -moz-box-shadow: 4px 4px 16px 1px rgba(0, 0, 0, 0.25);\n -webkit-box-shadow: 4px 4px 16px 1px rgba(0, 0, 0, 0.25);\n box-shadow: 4px 4px 16px 1px rgba(0, 0, 0, 0.25);\n}\nol,\nul {\n padding-left: 40px;\n margin: 10px 0;\n}\nol.compact li,\nul.compact li,\nol li.compact,\nul li.compact {\n font-size: 14px;\n}\nul.download {\n margin-top: 25px;\n}\nul.download li,\nul li.download,\nul.Download li,\nul li.Download {\n background: url(\"/images/download24.png\") no-repeat scroll left center\n transparent;\n font-weight: bold;\n list-style-type: none;\n margin: 0px 0 6px -40px;\n padding: 0 0 1px 30px;\n vertical-align: middle;\n}\n.callout {\n margin: 20px 0;\n background-color: #ffffe1;\n color: #333333;\n border: 1px solid #cccccc;\n padding: 15px;\n border-radius: 3px;\n -webkit-border-radius: 3px;\n -moz-border-radius: 3px;\n}\n.trace {\n padding: 20px;\n background-color: #eeeeee;\n color: #333333;\n border: 1px solid red;\n font-size: 13px;\n}\ntextarea,\ninput[type=\"text\"],\ninput[type=\"button\"],\ninput[type=\"submit\"] {\n -webkit-appearance: none;\n border-radius: 0;\n}\n.container-content {\n background-color: white;\n position: relative;\n zoom: 1;\n padding: 0 9px;\n cursor: default;\n}\n.container-content-wrap {\n margin: auto;\n max-width: 1270px;\n}\n.container-content pre,\n.container-code pre,\n.answer pre {\n white-space: pre-wrap;\n /* css-3 */\n white-space: -moz-pre-wrap;\n /* Mozilla, since 1999 */\n white-space: -pre-wrap;\n /* Opera 4-6 */\n white-space: -o-pre-wrap;\n /* Opera 7 */\n word-wrap: break-word;\n /* Internet Explorer 5.5+ */\n _white-space: pre;\n /* IE only hack to re-specify in addition to word-wrap */\n word-break: break-word;\n -ms-word-break: break-word;\n}\n.flex-container {\n display: -webkit-box;\n /* OLD - iOS 6-, Safari 3.1-6 */\n display: -moz-box;\n /* OLD - Firefox 19- (buggy but mostly works) */\n display: -ms-flexbox;\n /* TWEENER - IE 10 */\n display: -webkit-flex;\n /* NEW - Chrome */\n display: flex;\n /* NEW, Spec - Opera 12.1, Firefox 20+ */\n}\n.flex-extend {\n justify-content: space-between;\n}\n.flex-wrap {\n flex-wrap: wrap;\n}\n.flex-item {\n -webkit-box-flex: 1;\n /* OLD - iOS 6-, Safari 3.1-6 */\n -moz-box-flex: 1;\n /* OLD - Firefox 19- */\n -webkit-flex: 1;\n /* Chrome */\n -ms-flex: 1;\n /* IE 10 */\n flex: 1;\n}\n.flex-item-tight {\n flex: 0 1 auto;\n}\n.hover-container {\n display: block;\n position: relative;\n}\n.clearfix:after,\n.container:after {\n display: block;\n content: \".\";\n visibility: hidden;\n height: 0px;\n clear: both;\n}\n.clearfix,\n.container {\n display: inline-block;\n /* Mac IE5 sees this */\n /* Mac IE5 comment hack \\*/\n display: block;\n /* Mac IE5 doesn't see this, but everyone else does */\n}\n.access-link,\n.access-link img {\n position: absolute;\n top: 0px;\n left: 0px;\n width: 1px;\n height: 1px;\n z-index: 101;\n border-style: none;\n margin-top: -1px;\n overflow: hidden;\n}\n.site-top-menu {\n white-space: nowrap;\n position: absolute;\n z-index: 101;\n width: 100%;\n}\n.site-top-menu .main-content {\n width: 100%;\n}\n.site-top-menu .main-content .memberbar {\n margin-left: 90px;\n margin-right: 10px;\n}\n.site-top-menu.fixed .main-content {\n margin: auto;\n max-width: 1270px;\n}\n.site-header {\n background-image: url(\"/App_Themes/CodeProject/Img/logo135-bg.gif\");\n white-space: nowrap;\n overflow: hidden;\n}\n.site-header .main-content {\n position: relative;\n overflow: hidden;\n white-space: nowrap;\n}\n.site-header .logo {\n display: inline-block;\n}\n.site-header .promo {\n display: inline-block;\n position: absolute;\n top: 33px;\n right: 0;\n}\n.site-header.fixed .main-content {\n margin: auto;\n max-width: 1270px;\n}\n.sub-headerbar {\n padding-right: 9px;\n position: relative;\n margin: auto;\n max-width: 1270px;\n}\n.sub-headerbar-divider {\n margin-left: 10px;\n height: 1px;\n border-bottom: 1px solid #cccccc;\n position: absolute;\n bottom: 2px;\n left: 0px;\n right: 9px;\n}\n.memberbar {\n height: 25px;\n padding-top: 10px;\n color: #999999;\n font-size: 14px;\n}\n.memberbar a {\n color: #808080;\n font-size: 14px;\n}\ndiv.navbar {\n white-space: nowrap;\n}\n.navmenu {\n background: white;\n color: #4d4d4d;\n padding: 0px;\n margin: 0px;\n list-style: none;\n height: 25px;\n}\n.navmenu ul,\n.navmenu li {\n margin: 0;\n padding: 0;\n}\n.navmenu .has-submenu {\n position: absolute;\n right: 5px;\n padding-left: 10px;\n}\n.navmenu \u003e li:hover \u003e a,\n.navmenu \u003e li \u003e a:active {\n border: 1px solid #cccccc;\n}\n.navmenu ul,\n.navmenu \u003e li.open:hover \u003e a,\n.navmenu \u003e li.open \u003e a:active {\n border: 1px solid #cccccc;\n border-bottom-color: white;\n}\n.navmenu \u003e li {\n margin: 0 11px 2px 2px;\n}\n.navmenu \u003e li:active,\n.navmenu \u003e li:active \u003e a,\n.navmenu \u003e li:hover,\n.navmenu \u003e li \u003e a:active {\n background: white;\n color: #4d4d4d;\n}\n.navmenu \u003e li.openable \u003e a:active,\n.navmenu \u003e li.openable:hover \u003e a {\n /*border-bottom: 1px solid @ColourBack-Menu; */\n}\n.navmenu \u003e li \u003e a {\n padding: 2px 7px 6px 7px;\n border: 1px solid transparent;\n font-weight: bold;\n}\n.navmenu a {\n display: block;\n float: left;\n color: #666666;\n background: white;\n font-size: 17px;\n padding: 0px 9px;\n text-decoration: none;\n white-space: nowrap;\n}\n.navmenu a.fly {\n white-space: nowrap;\n}\n.navmenu ul {\n background: white;\n position: absolute;\n left: -9999px;\n top: -9999px;\n list-style: none;\n}\n.navmenu li {\n float: left;\n color: #4d4d4d;\n}\n.navmenu li.last {\n height: 9px;\n}\n.navmenu li a:active,\n.navmenu li a:hover {\n color: white;\n background-color: #ff9900;\n}\n.navmenu li \u003e a:active,\n.navmenu li:hover,\n.navmenu li:hover \u003e a,\n.navmenu li:hover.heading,\n.navmenu li a.selected {\n position: relative;\n color: white;\n background-color: #ff9900;\n}\n.navmenu li.openable:hover ul {\n left: 0px;\n top: 30px;\n z-index: 500;\n}\n.navmenu li.openable:hover \u003e ul ul {\n position: absolute;\n left: -9999px;\n top: -9999px;\n width: auto;\n}\n.navmenu li ul {\n border-bottom: 5px solid #ff9900;\n}\n.navmenu li li {\n float: none;\n}\n.navmenu li li a {\n float: none;\n font-size: 16px;\n font-weight: normal;\n}\n.navmenu li li a.fly {\n color: #4d4d4d;\n background-color: white;\n padding: 2px 20px;\n}\n.navmenu li li a.break {\n margin-bottom: 15px;\n}\n.navmenu li li a.highlight1,\n.navmenu li li a.highlight1:active,\n.navmenu li li a.highlight1:hover {\n background-color: #009900;\n}\n.navmenu li li a.highlight2,\n.navmenu li li a.highlight2:active,\n.navmenu li li a.highlight2:hover {\n background-color: #ff9900;\n}\n.navmenu li li a.highlight3,\n.navmenu li li a.highlight3:active,\n.navmenu li li a.highlight3:hover {\n background-color: #000000;\n}\n.navmenu li li a.highlight1,\n.navmenu li li a.highlight2,\n.navmenu li li a.highlight3 {\n color: white;\n font-size: 16px;\n margin: 5px 0;\n padding: 9px 20px;\n}\n.site-footer {\n display: -webkit-box;\n /* OLD - iOS 6-, Safari 3.1-6 */\n display: -moz-box;\n /* OLD - Firefox 19- (buggy but mostly works) */\n display: -ms-flexbox;\n /* TWEENER - IE 10 */\n display: -webkit-flex;\n /* NEW - Chrome */\n display: flex;\n /* NEW, Spec - Opera 12.1, Firefox 20+ */\n padding-top: 5px;\n width: 100%;\n font-size: 13px;\n color: #999999;\n}\n.site-footer .align-left,\n.site-footer .align-center,\n.site-footer .align-right {\n -webkit-box-flex: 1;\n /* OLD - iOS 6-, Safari 3.1-6 */\n -moz-box-flex: 1;\n /* OLD - Firefox 19- */\n -webkit-flex: 1;\n /* Chrome */\n -ms-flex: 1;\n /* IE 10 */\n flex: 1;\n}\n.site-footer .align-left {\n flex: 1 0 100px;\n}\n.site-footer .align-center {\n flex: 0 1 0%;\n white-space: nowrap;\n}\n.site-footer .align-right {\n flex: 1 0 100px;\n}\n.site-footer .page-width .active {\n border-bottom: 2px solid #ff9900;\n}\n.searchbar {\n padding: 0;\n}\n.searchbar .search {\n margin-bottom: 4px;\n padding: 2px 5px 0px;\n border: 1px solid #cccccc;\n}\n.searchbar .search.subdue {\n color: #cccccc;\n}\n.searchbar input.search {\n width: 190px;\n border: none;\n font-size: 13px;\n padding: 4px 2px;\n}\n.searchbar .search-advanced {\n padding: 8px;\n width: 203px;\n z-index: 1000;\n background-color: white;\n border: solid 1px #cccccc;\n position: absolute;\n top: -4px;\n right: 0px;\n}\n.searchbar .popup {\n display: none;\n}\n.sub-headerbar .searchbar {\n /*\n\t.search-advanced\n\t{\n .transition(width, .1s, linear);\n\n \u0026.open\n {\n \t\twidth: 320px;\n }\n }\n */\n}\n.sub-headerbar .searchbar input.search {\n /*\n \u0026:focus,\u0026:active\n {\n position : absolute;\n top : 3px;\n right : 36px;\n height : 19px;\n border : 1px solid #ccc;\n border-right : none;\n width: 300px;\n\n .transition(width, .1s, linear);\n }\n */\n}\n.search td {\n background-color: white;\n}\n.article-container-parts {\n display: -webkit-box;\n /* OLD - iOS 6-, Safari 3.1-6 */\n display: -moz-box;\n /* OLD - Firefox 19- (buggy but mostly works) */\n display: -ms-flexbox;\n /* TWEENER - IE 10 */\n display: -webkit-flex;\n /* NEW - Chrome */\n display: flex;\n /* NEW, Spec - Opera 12.1, Firefox 20+ */\n}\n.article-container {\n -webkit-box-flex: 1;\n /* OLD - iOS 6-, Safari 3.1-6 */\n -moz-box-flex: 1;\n /* OLD - Firefox 19- */\n -webkit-flex: 1;\n /* Chrome */\n -ms-flex: 1;\n /* IE 10 */\n flex: 1;\n background-color: white;\n color: #111111;\n zoom: 1;\n position: relative;\n max-width: 100%;\n min-height: 675px;\n}\n.article-container .article {\n margin: 0 20px 0 10px;\n line-height: 143%;\n}\n.article-container span.stats {\n margin-left: 30px;\n}\n.article-left-sidebar {\n width: 120px;\n min-width: 120px;\n min-height: 400px;\n font-size: 14px;\n border-right: 1px solid #f2f2f2;\n padding: 0;\n /* Old school style */\n /*\n .license {\n font-weight: bold;\n display: inline-block;\n margin-top: 10px;\n }\n */\n}\n.article-left-sidebar .article-left-sidebar-inner {\n width: 120px;\n min-width: 120px;\n}\n.article-left-sidebar .tabs \u003e div {\n padding: 5px 0 5px 10px;\n}\n.article-left-sidebar .selected {\n font-weight: bold;\n background: transparent url(\"/images/right-selected.gif\") no-repeat scroll\n right 9px;\n}\n.article-left-sidebar h4 {\n color: #ff9900;\n font-size: 14px;\n font-weight: bold;\n}\n.article-left-sidebar .stats div div div {\n padding: 0px 0 10px 10px;\n color: #666666;\n}\n.article-right-sidebar {\n width: 300px;\n margin-left: 10px;\n font-size: 14px;\n}\n.article-right-sidebar .header {\n font-size: 22px;\n color: white;\n background-color: #ff9900;\n padding: 8px;\n font-weight: 400;\n margin: 0;\n}\n.article-right-sidebar .reading-list-toc {\n max-height: 250px;\n overflow-y: auto;\n padding-right: 6px;\n margin-top: 5px;\n}\n.article-right-sidebar .reading-list-toc .count {\n font-weight: normal;\n font-size: 13px;\n}\n.article-right-sidebar .reading-list-toc .title {\n font-size: 16px;\n}\n.article-right-sidebar .content-list-item {\n display: -webkit-box;\n /* OLD - iOS 6-, Safari 3.1-6 */\n display: -moz-box;\n /* OLD - Firefox 19- (buggy but mostly works) */\n display: -ms-flexbox;\n /* TWEENER - IE 10 */\n display: -webkit-flex;\n /* NEW - Chrome */\n display: flex;\n /* NEW, Spec - Opera 12.1, Firefox 20+ */\n justify-content: space-between;\n font-size: 14px;\n margin: 4px 0;\n}\n.article-right-sidebar .content-list-item .count {\n width: 15%;\n padding: 0px;\n}\n.article-right-sidebar .content-list-item .title {\n width: 85%;\n font-weight: normal;\n}\n.article-right-sidebar .gototop {\n text-align: center;\n padding: 10px 0;\n opacity: 0;\n -webkit-transition: opacity 0.3s linear 0ms;\n -moz-transition: opacity 0.3s linear 0ms;\n -o-transition: opacity 0.3s linear 0ms;\n transition: opacity 0.3s linear 0ms;\n}\n.container-content .edit-links {\n margin: 21px 0 0 10px;\n}\n.article-summary {\n padding: 0px 10px 0px 10px;\n overflow: hidden;\n}\n.article h1 {\n margin: 0 0 15px 0;\n}\n.article h2 {\n color: #ff9900;\n}\n.article pre {\n overflow: auto;\n}\n.article .header .title {\n color: #808080;\n}\n.article .header .author {\n font-weight: bold;\n min-width: 100px;\n}\n.article .header .author a {\n color: #808080;\n}\n.article .header .avatar {\n max-width: 48px;\n max-height: 48px;\n overflow: unset;\n}\n.article .header .avatar-wrap {\n width: 48px;\n height: 48px;\n margin-right: 10px;\n text-align: center;\n}\n.article .header .date {\n white-space: nowrap;\n}\n.article .header .license {\n margin-left: 15px;\n}\n.article .header .stats {\n margin-left: 30px;\n}\n.article img.lazyload,\n.article img.lazyloading {\n opacity: 0;\n}\n.article img {\n max-width: 700px;\n height: auto;\n}\n.article img.lazyloaded {\n opacity: 1;\n transition: opacity 300ms;\n}\n.article .summary {\n color: #808080;\n padding: 40px 0 15px 0;\n}\n.article .text {\n padding-top: 10px;\n}\n.article .reading-list-nav {\n border-top: 1px #dedede solid;\n border-bottom: 1px #dedede solid;\n padding: 10px 0;\n}\n.article .reading-list-nav .prev {\n padding-left: 20px;\n}\n.article .reading-list-nav .next {\n margin-left: 5px;\n padding-right: 20px;\n text-align: right;\n}\n.article-nav {\n text-align: right;\n margin-top: 21px;\n vertical-align: middle;\n line-height: 15px;\n}\n.msg-728x90 {\n width: 728px;\n height: 90px;\n overflow: hidden;\n}\n.msg-300x250 {\n width: 300px;\n height: 250px;\n overflow: hidden;\n}\n.content-list {\n margin-bottom: 17px;\n}\n.content-list .count {\n font-weight: bold;\n font-size: 16px;\n color: #ff9900;\n padding: 3px;\n text-align: center;\n}\n.content-list-item {\n margin: 10px 0;\n}\n.content-list-item .title {\n font-size: 14px;\n font-weight: bold;\n padding: 0px 0;\n}\n.content-list-item .title a {\n color: #005782;\n}\n.tags {\n line-height: 190%;\n}\n.tags .t {\n background: none repeat scroll 0 0 transparent;\n border: 1px solid #fbedbb;\n border-radius: 12px 0 0 12px;\n line-height: 1.4;\n padding: 0 2px 2px 3px;\n position: relative;\n text-decoration: none;\n margin: 2px 5px 4px 0;\n white-space: nowrap;\n}\n.tags .t a {\n color: #666666;\n display: inline-block;\n margin-right: 3px;\n padding-left: 5px;\n text-overflow: ellipsis;\n}\n.container-breadcrumb {\n font-size: 14px;\n margin-top: 7px;\n color: #808080;\n margin: 12px 0 35px;\n}\n.container-breadcrumb a {\n color: #808080;\n}\n.pre-lang {\n display: -webkit-box;\n /* OLD - iOS 6-, Safari 3.1-6 */\n display: -moz-box;\n /* OLD - Firefox 19- (buggy but mostly works) */\n display: -ms-flexbox;\n /* TWEENER - IE 10 */\n display: -webkit-flex;\n /* NEW - Chrome */\n display: flex;\n /* NEW, Spec - Opera 12.1, Firefox 20+ */\n background-color: #fbedbb;\n justify-content: space-between;\n padding: 4px 8px;\n margin-top: 5px;\n color: #999999;\n border-bottom: solid 1px #ffd044;\n}\n.code-comment {\n color: #008000;\n font-style: italic;\n}\n.code-keyword {\n color: Blue;\n}\n.code-sdkkeyword {\n color: #339999;\n}\n.code-string {\n color: Purple;\n}\n.code-attribute {\n color: red;\n}\n.code-leadattribute {\n color: #800000;\n}\n.pre-action-link {\n font-size: 13px;\n color: #999999;\n}\n.pre-action-link span {\n cursor: pointer;\n margin: 0;\n -webkit-transition: color 0.1s linear;\n -moz-transition: color 0.1s linear;\n -o-transition: color 0.1s linear;\n transition: color 0.1s linear;\n}\n.speech-bubble-container-down,\n.speech-bubble-container-up,\n.speech-bubble-container-up-right,\n.speech-bubble-container-left,\n.speech-bubble-container-right {\n position: relative;\n}\n.speech-bubble-up,\n.speech-bubble-down,\n.speech-bubble-left,\n.speech-bubble-right,\n.speech-bubble-up-right {\n padding: 0.6em;\n border: 1px solid #cccccc;\n background-color: white;\n margin: 15px;\n text-decoration: none;\n font-weight: normal;\n text-align: left;\n white-space: normal;\n color: #333333;\n font-size: 14px;\n line-height: 1.3;\n}\n.speech-bubble-down {\n margin-bottom: 0px;\n}\n.tooltip .speech-bubble-up,\n.tooltip .speech-bubble-up-right,\n.tooltip .speech-bubble-down,\n.tooltip .speech-bubble-left,\n.tooltip .speech-bubble-right {\n -moz-box-shadow: 4px 4px 16px 1px rgba(0, 0, 0, 0.25);\n -webkit-box-shadow: 4px 4px 16px 1px rgba(0, 0, 0, 0.25);\n box-shadow: 4px 4px 16px 1px rgba(0, 0, 0, 0.25);\n border-radius: 5px;\n -webkit-border-radius: 5px;\n -moz-border-radius: 5px;\n min-width: 75px;\n}\n.speech-bubble-pointer-down,\n.speech-bubble-pointer-down-inner {\n width: 0;\n height: 0;\n border-bottom-width: 0;\n background: none;\n}\n.speech-bubble-pointer-down {\n border-left: 7px solid transparent;\n border-right: 7px solid transparent;\n border-top: 1px solid #cccccc;\n border-top-width: 14px;\n margin-left: 35px;\n margin-bottom: 15px;\n _display: none;\n}\n.speech-bubble-pointer-up,\n.speech-bubble-pointer-up-right,\n.speech-bubble-pointer-up-inner,\n.speech-bubble-pointer-up-right-inner {\n width: 0;\n height: 0;\n border-top-width: 0;\n background: none;\n}\n.speech-bubble-pointer-up,\n.speech-bubble-pointer-up-right {\n border-left: 5px solid transparent;\n border-right: 5px solid transparent;\n border-bottom: 1px solid #cccccc;\n border-bottom-width: 14px;\n margin-left: 35px;\n position: absolute;\n top: -12px;\n _display: none;\n}\n.speech-bubble-container-up-right .speech-bubble-pointer-up-right {\n margin-left: 0;\n margin-right: 0px;\n right: 35px;\n}\n.tooltip {\n position: relative;\n text-decoration: none;\n}\n.tooltip .speech-bubble-container-up,\n.tooltip .speech-bubble-container-down,\n.tooltip .speech-bubble-container-left,\n.tooltip .speech-bubble-container-right,\n.tooltip .speech-bubble-container-up-right,\n.tooltip .tooltip-flyout {\n display: none;\n opacity: 0;\n -webkit-transition: opacity 0.5s linear 0ms;\n -moz-transition: opacity 0.5s linear 0ms;\n -o-transition: opacity 0.5s linear 0ms;\n transition: opacity 0.5s linear 0ms;\n}\n.micromodal {\n display: none;\n}\n.micromodal .modal__overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n justify-content: center;\n align-items: center;\n background: rgba(0, 0, 0, 0.65);\n z-index: 1000;\n}\n.micromodal .modal__container {\n box-sizing: border-box;\n overflow-y: auto;\n max-width: 500px;\n max-height: 100vh;\n padding: 30px;\n background-color: #fff;\n border-radius: 4px;\n}\n.micromodal .modal__container,\n.micromodal .modal__overlay {\n will-change: transform;\n}\n.micromodal .modal_header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 1rem;\n}\n.micromodal .modal_title {\n margin-top: 0;\n margin-bottom: 0;\n color: #ff9900;\n box-sizing: border-box;\n}\n.bottom-promo {\n height: 90px;\n margin-top: 10px;\n overflow: hidden;\n}\n.bottom-promo .msg-728x90 {\n width: 728px;\n margin: 0 auto;\n}\n.msg-728x90 {\n overflow: hidden;\n position: relative;\n height: 90px;\n min-width: 728px;\n}\ntable.forum {\n table-layout: fixed;\n margin: 0 0 20px 0;\n padding: 0px;\n width: 100%;\n}\n.forum {\n /*\n .indent\n {\n padding-left:5px; padding-right: 5px;\n }\n */\n}\n.forum table {\n border-collapse: separate;\n}\n.forum .header1,\n.forum .header1 TD {\n color: #333333;\n font-size: 14px;\n vertical-align: middle;\n}\n.forum .header2,\n.forum .header2 TD {\n color: white;\n background-color: #ff9900;\n font-size: 14px;\n vertical-align: middle;\n}\n.forum .header2 input,\n.forum .header2 TD input,\n.forum .header2 select,\n.forum .header2 TD select {\n padding: 2px;\n}\n.forum .button {\n border: 1px solid #ffcc66;\n margin: 1px;\n}\n.forum .searchbar {\n border: 1px solid #cccccc;\n padding: 4px 0 0 0;\n margin: 3px 0;\n}\n.forum .searchbar .search {\n width: 200px;\n}\n.forum .searchbar input[type=\"image\"] {\n vertical-align: middle;\n}\n.forum .dropdown {\n background-color: #fffdfa;\n font-size: 95%;\n margin-left: 5px;\n}\n.forum .footer,\n.forum .footer td,\n.forum .navbar,\n.forum .navbar td {\n font-size: 14px;\n padding: 8px 0;\n border: 0;\n border-top: 1px solid #808080;\n}\n.author-wrapper {\n position: relative;\n}\n.author-wrapper .profile-pic {\n border: 1px solid #333;\n margin: 0 13px 0 0;\n padding: 10px;\n -moz-box-shadow: 3px 3px 5px 1px rgba(0, 0, 0, 0.2);\n -webkit-box-shadow: 3px 3px 5px 1px rgba(0, 0, 0, 0.2);\n box-shadow: 3px 3px 5px 1px rgba(0, 0, 0, 0.2);\n max-height: 100px;\n}\n.author-wrapper .container-member .author {\n font-size: 29px;\n color: #333333;\n font-weight: 600;\n}\n.member-signin .forgot {\n padding: 0;\n}\n.member-signin a.forgot {\n color: #808080;\n}\n.rating-container {\n /*\n\t.rating-close\n\t{\n\t\tfont-size : @FontSize-MediumSmall;\n\t\tfont-weight : bold;\n\t\t// display : inline-block;\n\t\t// height : 19px;\n\t\tpadding : 0px 7px 3px 5px;\n\t\ttext-decoration : none;\n\t\tborder : 1px solid transparent;\n\t\tposition : absolute;\n\t\tright : 1px;\n\t\ttop : -1px;\n\n\t\t\u0026:hover { border : 1px solid @Colour-Theme1; }\n\t}*/\n}\n.rating-container .rating-prompt {\n padding-right: 5px;\n white-space: nowrap;\n line-height: 25px;\n margin-right: 2px;\n font-weight: bold;\n color: #808080;\n}\n.rating-container .rating-votes {\n margin-left: 5px;\n}\n.rating-container.large-stars,\n.rating-container.medium-stars,\n.rating-container.small-stars {\n margin-left: 7px;\n}\n.rating-container.large-stars .rating-votes,\n.rating-container.large-stars .rating-prompt,\n.rating-container.large-stars .rating-poor,\n.rating-container.large-stars .rating-good {\n line-height: 25px;\n}\n.tablet-only,\n.tablet-block-only {\n display: none;\n}\n.mobile-only,\n.mobile-block-only {\n display: none;\n}\n.desktop-only.tablet-only {\n display: inherit;\n}\n.tablet-only.desktop-only {\n display: inherit;\n}\n.rrssb-buttons,\n.rrssb-buttons li,\n.rrssb-buttons li a {\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n.clearfix:after {\n clear: both;\n}\n.clearfix:before,\n.clearfix:after {\n content: \" \";\n display: table;\n}\n.rrssb-buttons {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n height: 40px;\n margin: 0;\n padding: 0;\n width: 100%;\n}\n.rrssb-buttons li {\n float: left;\n height: 100%;\n list-style: none;\n margin: 0;\n padding: 0 2.5px;\n line-height: 13px;\n}\n.rrssb-buttons li.email a {\n background-color: #0a88ff;\n}\n.rrssb-buttons li.facebook a {\n background-color: #306199;\n}\n.rrssb-buttons li.linkedin a {\n background-color: #007bb6;\n}\n.rrssb-buttons li.twitter a {\n background-color: #26c4f1;\n}\n.rrssb-buttons li.reddit a {\n background-color: #8bbbe3;\n}\n.rrssb-buttons li.pinterest a {\n background-color: #b81621;\n}\n.rrssb-buttons li.compact {\n padding: 0 4.5px;\n}\n.rrssb-buttons li.compact a {\n border-radius: 50%;\n padding: 0px 7px 0 32px;\n}\n.rrssb-buttons li.compact a .icon {\n left: 7px;\n top: -3px;\n width: 5%;\n transform: scale(0.85);\n}\n.rrssb-buttons li.compact a .icon svg {\n height: auto;\n width: auto;\n}\n.rrssb-buttons li a {\n background-color: #ccc;\n border-radius: 3px;\n display: block;\n font-size: 11px;\n font-weight: bold;\n height: 100%;\n padding: 11px 7px 12px 27px;\n position: relative;\n text-align: center;\n text-decoration: none;\n text-transform: uppercase;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n width: 100%;\n -webkit-transition: background-color 0.2s ease-in-out;\n -moz-transition: background-color 0.2s ease-in-out;\n -o-transition: background-color 0.2s ease-in-out;\n transition: background-color 0.2s ease-in-out;\n}\n.rrssb-buttons li a .icon {\n display: block;\n height: 100%;\n left: 10px;\n padding-top: 9px;\n position: absolute;\n top: 0;\n width: 10%;\n}\n.rrssb-buttons li a .icon svg {\n height: 17px;\n width: 17px;\n}\n.rrssb-buttons li a .icon svg path,\n.rrssb-buttons li a .icon svg polygon {\n fill: #fff;\n}\n.cc-window {\n opacity: 1;\n background-color: #ff9900;\n /*\n -webkit-transition: opacity .25s ease;\n -moz-transition: opacity .25s ease;\n -ms-transition: opacity .25s ease;\n -o-transition: opacity .25s ease;\n transition: opacity .25s ease;\n */\n}\n.cc-window.cc-invisible {\n opacity: 0;\n}\n.cc-animate.cc-revoke {\n /*\n -webkit-transition: transform .25s ease;\n -moz-transition: transform .25s ease;\n -ms-transition: transform .25s ease;\n -o-transition: transform .25s ease;\n transition: transform .25s ease;\n */\n}\n.cc-animate.cc-revoke.cc-bottom {\n transform: translateY(2em);\n}\n.cc-window,\n.cc-revoke {\n position: fixed;\n overflow: hidden;\n box-sizing: border-box;\n /* exclude padding when dealing with width */\n font-family: \"Segoe UI\", Arial, Sans-Serif;\n font-size: 13px;\n /* by setting the base font here, we can size the rest of the popup using CSS `em` */\n line-height: 1.5em;\n display: flex;\n flex-wrap: nowrap;\n /* the following are random unjustified styles - just because - should probably be removed */\n z-index: 9999;\n}\n.cc-window.cc-banner {\n padding: 0.7em 1.8em;\n width: 100%;\n flex-direction: row;\n}\n.cc-revoke {\n padding: 0.5em;\n}\n.cc-btn,\n.cc-link,\n.cc-close,\n.cc-revoke {\n cursor: pointer;\n}\n.cc-link {\n opacity: 0.8;\n display: inline-block;\n padding: 0.2em;\n text-decoration: underline;\n}\n.cc-link:active,\n.cc-link:visited {\n color: initial;\n}\n.cc-btn {\n display: block;\n padding: 0.4em 0.8em;\n font-size: 0.9em;\n font-weight: bold;\n border-width: 2px;\n border-style: solid;\n text-align: center;\n white-space: nowrap;\n}\n.cc-banner .cc-btn:last-child {\n min-width: 110px;\n margin-left: 10px;\n}\n.cc-highlight .cc-btn:first-child {\n background-color: transparent;\n border-color: transparent;\n}\n.cc-revoke.cc-bottom {\n bottom: 0;\n left: 3em;\n border-top-left-radius: 0.5em;\n border-top-right-radius: 0.5em;\n}\n.cc-bottom {\n bottom: 1em;\n}\n.cc-window.cc-banner {\n align-items: center;\n}\n.cc-banner.cc-bottom {\n left: 0;\n right: 0;\n bottom: 0;\n}\n.cc-banner .cc-message {\n flex: 1;\n}\n.cc-compliance {\n display: flex;\n align-items: center;\n align-content: space-between;\n}\n.cc-compliance \u003e .cc-btn {\n flex: 1;\n}\n.cc-btn + .cc-btn {\n margin-left: 0.5em;\n}\n\n@keyframes showcopied {\n 0% {\n opacity: 0;\n }\n 70% {\n opacity: 1;\n }\n 100% {\n opacity: 0;\n }\n}\n"])</script><script>self.__next_f.push([1,"1a:T48a7,"])</script><script>self.__next_f.push([1,"\u003cUL class=download\u003e\r\n\u003cLI\u003e\u003cA href=\"adaptingGRML/ServerScripts.zip\"\u003eDownload source code - 7.26 Kb\u003c/A\u003e \u003c/LI\u003e\u003c/UL\u003e\r\n\u003cP\u003e\u003cIMG height=372 src=\"adaptingGRML/PRM1_000.jpg\" width=500\u003e\u003c/P\u003e\r\n\u003cH2\u003eIntroduction\u003c/H2\u003e\r\n\u003cP\u003eThis article introduces the process of adapting (or converting) a web page from one markup language to another. It discusses how to adapt a HTML web page to GRML. Two examples are provided. The first demonstrates how to extract hyperlinks from an HTML web page and convert it to GRML. The second demonstrates how to do this with images. These examples require server-side processing. Here, IIS, Active Server Pages (ASP), and PERL are used.\u003c/P\u003e\r\n\u003cH2\u003eBackground\u003c/H2\u003e\r\n\u003cP\u003eIt is recommended to have some experience with ASP and PERL. PERL has regular expression support that is used to extract the hyperlinks and images from the web page. Any server-side scripting environment does this, including .NET, CGI, or PHP. However, PERL and ASP are used for this article. While PERL is required, the server-side scripting language specifically used is PerlScript. To use PerlScript, download a PERL interpreter. To get one that works with IIS, try \u003cA href='http://www.activestate.com/Products/Download/Download.plex?id=\"ActivePerl\"' target=_blank\u003eActivePerl\u003c/A\u003e. If not done already, read \u003cA href=\"http://www.codeproject.com/html/GRMLbrowser.asp\"\u003eIntroducing GRML\u003c/A\u003e and \u003cA href=\"http://grmlbrowser.com/articles/GRML_001\" target=_blank\u003eUsing GRML\u003c/A\u003e. These articles provide explanations of what GRML is and how it is used.\u003c/P\u003e\r\n\u003cH2\u003eWhat is an Adapter?\u003c/H2\u003e\r\n\u003cP\u003eAn adapter is generally defined as...\u003c/P\u003e\r\n\u003cBLOCKQUOTE\u003e\r\n\u003cP\u003ean object that converts the original interface of a component to another interface.\u003c/P\u003e\u003c/BLOCKQUOTE\u003e\r\n\u003cP\u003eFor the purposes of this article, the definition of an adapter is...\u003c/P\u003e\r\n\u003cBLOCKQUOTE\u003e\r\n\u003cP\u003eserver-side processing or scripting that converts one markup language to another.\u003c/P\u003e\u003c/BLOCKQUOTE\u003e\r\n\u003cP\u003eThis definition describes converting HTML to GRML using ASP. The adapter object is the ASP scripting, the original interface is HTML, and the other interface is GRML.\u003c/P\u003e\r\n\u003cP\u003eDepending on what is being converted, adapters need to read from the original interface and write to the other interface. In other words, an adapter needs an interface reader and an interface writer. A HTML to GRML adapter requires a HTML reader and a GRML writer.\u003c/P\u003e\r\n\u003cH2\u003eAdapting hyperlinks and images\u003c/H2\u003e\r\n\u003cP\u003eHTML does not describe many elements of its content. For example, there is no way to determine the attributes of one text block from another. However, not all HTML content is without description. It does have specific tags for hyperlinks and images.\u003c/P\u003e\r\n\u003cP\u003eUsing a specific tag to identify content makes it possible to create a script that reads only those tags. When found, the unwanted tag elements are removed, leaving only the content. The script then writes the content in the new format or markup language. This is how it adapts HTML hyperlinks or images to GRML.\u003c/P\u003e\r\n\u003cH2\u003eThe Hyperlink adapter\u003c/H2\u003e\r\n\u003cP\u003eThe use of the \u003cCODE lang=html\u003e\u003cspan class=\"code-keyword\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"code-leadattribute\"\u003ea\u003c/span\u003e \u003cspan class=\"code-attribute\"\u003ehref\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e\u0026gt;\u003c/span\u003e\u003c/CODE\u003e tag allows a HTML web browser to identify which text is a hyperlink. This tag is the basis for the hyperlink adapter. It extracts all hyperlinks from an HTML web page and converts them to GRML.\u003c/P\u003e\r\n\u003cP\u003eBelow is an example of a HTML to GRML hyperlinks adapter, using PerlScript:\u003c/P\u003e\u003cPRE lang=perlscript\u003e\u003cspan class=\"code-pagedirective\"\u003e\u0026lt;%@\u003c/span\u003e\u003cspan class=\"code-leadattribute\"\u003e Language\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u0026quot;\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003ePerlScript%\u0026quot;\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e\u0026gt;\r\n\u0026lt;HTML\u0026gt;\r\n\u0026lt;center\u0026gt;\r\n\u0026lt;form action\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=links.asp\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e\u0026gt;\r\nURL to extract: \u0026lt;input type\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=text\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e name\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=url1\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e length\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=60\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e\u0026gt;\r\n\u0026lt;input type\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=submit\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e\u0026gt;\r\n\u0026lt;/form\u0026gt;\r\n\u0026lt;/center\u0026gt;\r\n\u0026lt;!--\r\n\u0026lt;grml\u0026gt;\r\n\u0026lt;edit url1\u0026gt;\r\n\u0026lt;title\u0026gt;Enter URL:\u0026gt;\r\n\u0026lt;%\r\nuse HTML::LinkExtor;\r\nuse URI::URL;\r\nuse LWP;\r\n\r\nmy $url, $html;\r\n\r\n# Parsing the Request\r\n$url \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $Request-\u0026gt;QueryString(\u0026quot;url1\u0026quot;)-\u0026gt;Item();\r\n\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;submit\u0026gt;\\n\u0026quot;);\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;location\u0026gt;GRMLBrowser.com/links.asp\\n\u0026quot;);\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;/submit\u0026gt;\\n\u0026quot;);\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;edit url1\u0026gt;\\n\u0026quot;);\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;text\u0026gt;$url\\n\u0026quot;);\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;/edit\u0026gt;\\n\u0026quot;);\r\n\r\nif ($url eq \u0026quot;\u0026quot;)\r\n{\r\n $Response-\u0026gt;Write(\u0026quot;\u0026lt;/GRML\u0026gt;\\n\u0026quot;);\r\n}\r\nelse\r\n{\r\n if ($url !~ /http:\\/\\//)\r\n {\r\n $url \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e= \u0026quot;\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003ehttp://\u0026quot;\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e. $url;\r\n }\r\n}\r\n\r\n# Constructing the Request\r\n $_ \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $sites;\r\n\r\n# Retrieving the Response/Resultset\r\n# - Filtering the Resultset (optional)\r\nmy $ua \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e LWP::UserAgent-\u0026gt;new(agent \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e\u0026gt; \u0026quot;Mozilla 4.0\u0026quot;);\r\nmy $request \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e HTTP::Request-\u0026gt;new('GET', $url);\r\nmy $response \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $ua-\u0026gt;request($request);\r\n\r\nunless ($response-\u0026gt;is_success)\r\n{\r\n print $response-\u0026gt;error_as_HTML . \u0026quot;\\n\u0026quot;;\r\n exit(1);\r\n}\r\n\r\nmy $res \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $response-\u0026gt;content(); # content without HTTP header\r\n\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;column\u0026gt;\\n\u0026quot;);\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;Title\u0026gt;\\n\u0026quot;);\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;Request\u0026gt;\\n\u0026quot;);\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;link\u0026gt;\\n\u0026quot;);\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;/column\u0026gt;\\n\u0026quot;);\r\n\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;result\u0026gt;\\n\u0026quot;);\r\n\r\n$res \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\\n/ /gsi;\r\n\r\nwhile($res \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e m|href\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=(.+?)\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e\u0026gt;(.*?)\u0026lt;/A\u0026gt;|gsi) ## that's all ...\r\n{\r\n my $temp_link \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $1;\r\n my $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $2;\r\n \r\n $temp_link \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\\'//gsi;\r\n $temp_link \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\\\u0026quot;//gsi;\r\n $temp_link \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/ (.*)//gsi;\r\n $temp_link \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\u0026lt;b\u0026gt;//gsi;\r\n $temp_link \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\u0026lt;\\/b\u0026gt;//gsi;\r\n $temp_link \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\u0026amp;amp;/\\\u0026amp;/gsi;\r\n $temp_link \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\\n(.*)//gsi;\r\n $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\u0026lt;b\u0026gt;//gsi;\r\n $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\u0026lt;\\/b\u0026gt;//gsi;\r\n $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\u0026lt;(.+?)\u0026gt;//gsi;\r\n $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\u0026lt;\\/font\u0026gt;//gsi;\r\n $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\u0026amp;amp;/\\\u0026amp;/gsi;\r\n $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/ / /gsi;\r\n $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\u0026amp;quot;/\\\u0026quot;/gsi;\r\n $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\\n(.*)//gsi;\r\n $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\\n/ /gsi;\r\n $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/ (.*)//gsi;\r\n $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/ (.*)//gsi;\r\n \r\n\r\n if ($temp_item !~ /img src\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=/)\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e\r\n {\r\n if ($temp_link !~ /$url/ \u0026amp;\u0026amp; $temp_link !~ /\\/\\//)\r\n {\r\n $temp_link \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $url . \u0026quot;\\/\u0026quot; . $temp_link;\r\n }\r\n\r\n $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\\n//gsi;\r\n $temp_link \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\\n//gsi;\r\n\r\n $Response-\u0026gt;Write(\u0026quot;\u0026lt;link\u0026gt;$temp_link\\n\u0026quot;);\r\n $Response-\u0026gt;Write(\u0026quot;\u0026lt;title\u0026gt;$temp_item\\n\u0026quot;); \r\n }\r\n\r\n $Response-\u0026gt;Write(\u0026quot;\u0026lt;request\u0026gt;$url\\n\u0026quot;);\r\n $Response-\u0026gt;Write(\u0026quot;\\n\\n\u0026quot;);\r\n}\r\n\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;/result\u0026gt;\\n\u0026quot;);\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;/GRML\u0026gt;\\n\u0026quot;);\r\n\u003c/span\u003e\u003cspan class=\"code-pagedirective\"\u003e%\u0026gt;\u003c/span\u003e\r\n--\u0026gt;\r\n\u003cspan class=\"code-keyword\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e/\u003c/span\u003e\u003cspan class=\"code-leadattribute\"\u003ehtml\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e\u0026gt;\u003c/span\u003e\u003c/PRE\u003e\r\n\u003cP\u003eWhat the above code does is it creates a form in HTML that extracts all the hyperlinks from a web page. The hyperlinks (and their titles) are formatted using GRML. To view GRML, a GRML web browser is required (such as \u003cA href=\"http://grmlbrowser.com/downloads\" target=_blank\u003ePioneer Report MDI\u003c/A\u003e).\u003c/P\u003e\r\n\u003cP\u003eAll of the server-side scripting is used as the HTML reader. Only the following lines are used as the GRML writer. They are:\u003c/P\u003e\r\n\u003cUL\u003e\r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003ccolumn\u003e\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003cTitle\u003e\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003cRequest\u003e\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003clink\u003e\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003c/column\u003e\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003cresult\u003e\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003clink\u003e$temp_link\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003ctitle\u003e$temp_item\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003crequest\u003e$url\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003c/result\u003e\\n\");\u003c/CODE\u003e \u003c/LI\u003e\u003c/UL\u003e\r\n\u003cP\u003eOnly the last three lines format the hyperlinks using GRML. The first two lines create the form in the browser window of a GRML web browser and do not use the adapted HTML hyperlinks.\u003c/P\u003e\r\n\u003cP\u003eTo see the above in action, go to \u003cA href=\"http://grmlbrowser.com/links.asp\" target=_blank\u003eHyperlink adapter\u003c/A\u003e or copy the above script to a file and host it from a local web server. Once the web page is displayed, enter a URL and press the 'Submit' button. It displays all the hyperlinks extracted from the HTML web page formatted in GRML.\u003c/P\u003e\r\n\u003cP\u003eAfter adapting hyperlinks from HTML to GRML, this is how it appears in a GRML web browser (using Pioneer Report MDI):\u003c/P\u003e\r\n\u003cP\u003e\u003cIMG height=351 src=\"adaptingGRML/PRM1_001.jpg\" width=425\u003e\u003c/P\u003e\r\n\u003cH2\u003eThe Image adapter\u003c/H2\u003e\r\n\u003cP\u003eUsing the \u003cCODE lang=html\u003e\u003cspan class=\"code-keyword\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"code-leadattribute\"\u003eimg\u003c/span\u003e \u003cspan class=\"code-attribute\"\u003esrc\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e\u0026gt;\u003c/span\u003e\u003c/CODE\u003e tag, a script is able to find and extract images from HTML. By reading this tag and removing unwanted tag elements, the HTML images are converted to GRML. The following script demonstrates this:\u003c/P\u003e\u003cPRE lang=perlscript\u003e\u003cspan class=\"code-pagedirective\"\u003e\u0026lt;%@\u003c/span\u003e\u003cspan class=\"code-leadattribute\"\u003e Language\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u0026quot;\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003ePerlScript%\u0026quot;\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e\u0026gt; \r\n\u0026lt;center\u0026gt; \r\n\u0026lt;form action\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=translate.asp\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e\u0026gt; \r\nURL to translate: \u0026lt;input type\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=text\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e name\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=url1\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e length\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=60\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e\u0026gt; \r\n\u0026lt;input type\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=submit\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e\u0026gt; \r\n\u0026lt;/form\u0026gt; \r\n\u0026lt;/center\u0026gt; \r\n\r\n\u0026lt;!-- \r\n\u0026lt;grml\u0026gt; \r\n\u0026lt;edit url1\u0026gt; \r\n\u0026lt;title\u0026gt;Enter URL: \r\n\u0026lt;/edit\u0026gt; \r\n\r\n\u0026lt;% \r\nuse HTML::LinkExtor; \r\nuse URI::URL; \r\nuse LWP;\r\n\r\nmy $url, $html;\r\n\r\n# Parsing the Request\r\n$url \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $Request-\u0026gt;QueryString(\u0026quot;url1\u0026quot;)-\u0026gt;Item();\r\n\r\nif ($url eq \u0026quot;\u0026quot;)\r\n{\r\n $Response-\u0026gt;Write(\u0026quot;\u0026lt;/GRML\u0026gt;\\n\u0026quot;);\r\n}\r\nelse\r\n{\r\n if ($url !~ /http:\\/\\//)\r\n {\r\n $url \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e= \u0026quot;\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003ehttp://\u0026quot;\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e . $url;\r\n }\r\n}\r\n\r\n$Response-\u0026gt;Write(\u0026quot;### URL ###\\n\\n\u0026quot;);\r\n$Response-\u0026gt;Write(\u0026quot;The url is: $url\\n\\n\u0026quot;);\r\n\r\n# Constructing the Request\r\n$_ \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $sites;\r\n\r\n# Retrieving the Response/Results\r\n# - Filtering the Results (optional)\r\nmy $ua \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e LWP::UserAgent-\u0026gt;new(agent \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e\u0026gt; \u0026quot;my agent V1.00\u0026quot;);\r\nmy $request \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e HTTP::Request-\u0026gt;new('GET', $url);\r\nmy $response \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $ua-\u0026gt;request($request);\r\n\r\nunless ($response-\u0026gt;is_success)\r\n{\r\n print $response-\u0026gt;error_as_HTML . \u0026quot;\\n\u0026quot;;\r\n exit(1);\r\n}\r\n\r\nmy $res \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $response-\u0026gt;content(); # content without HTTP header\r\n\r\nmy @imgs \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e ();\r\nmy @hrefs \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e ();\r\n\r\n# Make the parser. Unfortunately, we don't know the base yet\r\n# (it might be diffent from $url)\r\nmy $p \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e HTML::LinkExtor-\u0026gt;new(\\\u0026amp;callback);\r\n\r\n$p-\u0026gt;parse($res);\r\n\r\n# Expand all image URLs to absolute ones\r\nmy $base \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $response-\u0026gt;base;\r\n\r\n@imgs \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e map { $_ \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e url($_, $base)-\u0026gt;abs; } @imgs;\r\n\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;column\u0026gt;\\n\u0026quot;); \r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;image\u0026gt;\\n\u0026quot;); \r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;link\u0026gt;\\n\u0026quot;); \r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;/column\u0026gt;\\n\\n\u0026quot;); \r\n\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;result\u0026gt;\\n\u0026quot;); \r\n\r\nforeach (@imgs)\r\n{\r\n $Response-\u0026gt;Write(\u0026quot;\u0026lt;image\u0026gt;$_\\n\u0026quot;);\r\n}\r\n\r\n$Response-\u0026gt;Write(\u0026quot;\\nLinks:\\n\u0026quot;);\r\n\r\nforeach (@hrefs)\r\n{\r\n my $temp \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $_;\r\n\r\n if ($temp !~ /$url/ \u0026amp;\u0026amp; $temp !~ /\\/\\//)\r\n {\r\n $temp \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $url . \u0026quot;\\/\u0026quot; . $temp;\r\n }\r\n\r\n $Response-\u0026gt;Write(\u0026quot;\u0026lt;link\u0026gt;$temp\\n\u0026quot;);\r\n}\r\n\r\nsub callback\r\n{\r\n my($tag, %attr) \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e @_;\r\n\r\n push(@imgs , values %attr) if $tag eq 'img';\r\n push(@hrefs, values %attr) if $tag eq 'a';\r\n}\r\n\r\n\u003c/span\u003e\u003cspan class=\"code-pagedirective\"\u003e%\u0026gt;\u003c/span\u003e\r\n\u003cspan class=\"code-keyword\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e/\u003c/span\u003e\u003cspan class=\"code-leadattribute\"\u003eresult\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e\u0026gt;\u003c/span\u003e\r\n\u003cspan class=\"code-keyword\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e/\u003c/span\u003e\u003cspan class=\"code-leadattribute\"\u003eGRML\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e\u0026gt;\u003c/span\u003e\r\n--\u0026gt;\u003c/PRE\u003e\r\n\u003cP\u003eThe above script is used as an HTML reader, except for the lines used to build the columns and each result. These lines are the GRML writer:\u003c/P\u003e\r\n\u003cUL\u003e\r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003ccolumn\u003e\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003cimage\u003e\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003clink\u003e\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003c/column\u003e\\n\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003cresult\u003e\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003cimage\u003e$_\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003clink\u003e$temp\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003c/result\u003e\\n\");\u003c/CODE\u003e \u003c/LI\u003e\u003c/UL\u003e\r\n\u003cP\u003eOnce the image content has been adapted to GRML, this is how it looks in a GRML web browser (using Pioneer Report MDI):\u003c/P\u003e\r\n\u003cP\u003e\u003cIMG height=351 src=\"adaptingGRML/PRM1_002.jpg\" width=425\u003e\u003c/P\u003e\r\n\u003cH2\u003eConclusion\u003c/H2\u003e\r\n\u003cP\u003eConverting HTML to GRML is possible when using an adapter. Only the content with identifiable tags are adaptable from one markup language to another. In the case of HTML, there are tags to identify hyperlinks and images.\u003c/P\u003e\r\n\u003cP\u003eThe examples described for adapting content show how to convert HTML hyperlinks or images to GRML. The adapter consists of a HTML reader and a GRML writer. Using this adapter, a web page viewed with a HTML web browser is viewable using a GRML web browser.\u003c/P\u003e\r\n\u003cH2\u003eLatest changes\u003c/H2\u003e\r\n\u003cUL\u003e\r\n\u003cLI\u003e09/03/04 \r\n\u003cUL\u003e\r\n\u003cLI\u003eUsing GRML v1.2 in code samples. \u003c/LI\u003e\u003c/UL\u003e\r\n\u003cLI\u003e10/08/04 \r\n\u003cUL\u003e\r\n\u003cLI\u003eUsing GRML v2.3 in code samples. Pioneer Report MDI 3.64 uses GRML\u0026nbsp;v1.2 while all other GRML web browsers use v2.3. \u003c/LI\u003e\u003c/UL\u003e\u003c/LI\u003e\u003c/UL\u003e\r\n\r\n"])</script><script>self.__next_f.push([1,"9:[\"$\",\"div\",null,{\"className\":\"custom-container flex px-2 gap-8 overflow-hidden\",\"children\":[[\"$\",\"div\",null,{\"className\":\"w-[948px] max-w-full\",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex gap-2 mb-2 flex-wrap\",\"children\":[[\"$\",\"a\",\"Perl\",{\"rel\":\"tag\",\"href\":\"/Tags/Perl\",\"className\":\"px-2 border border-border-yellow rounded-l-full text-gray-light visited:text-gray-light hover:underline hover:bg-yellow-light\",\"children\":\"Perl\"}],[\"$\",\"a\",\"IIS\",{\"rel\":\"tag\",\"href\":\"/Tags/IIS\",\"className\":\"px-2 border border-border-yellow rounded-l-full text-gray-light visited:text-gray-light hover:underline hover:bg-yellow-light\",\"children\":\"IIS\"}],[\"$\",\"a\",\"Windows 2003\",{\"rel\":\"tag\",\"href\":\"/Tags/Win2003\",\"className\":\"px-2 border border-border-yellow rounded-l-full text-gray-light visited:text-gray-light hover:underline hover:bg-yellow-light\",\"children\":\"Windows 2003\"}],[\"$\",\"a\",\"Windows 2000\",{\"rel\":\"tag\",\"href\":\"/Tags/Win2K\",\"className\":\"px-2 border border-border-yellow rounded-l-full text-gray-light visited:text-gray-light hover:underline hover:bg-yellow-light\",\"children\":\"Windows 2000\"}],[\"$\",\"a\",\"ASP\",{\"rel\":\"tag\",\"href\":\"/Tags/ASP\",\"className\":\"px-2 border border-border-yellow rounded-l-full text-gray-light visited:text-gray-light hover:underline hover:bg-yellow-light\",\"children\":\"ASP\"}],[\"$\",\"a\",\"Windows XP\",{\"rel\":\"tag\",\"href\":\"/Tags/WinXP\",\"className\":\"px-2 border border-border-yellow rounded-l-full text-gray-light visited:text-gray-light hover:underline hover:bg-yellow-light\",\"children\":\"Windows XP\"}],[\"$\",\"a\",\"Intermediate\",{\"rel\":\"tag\",\"href\":\"/Tags/Intermediate\",\"className\":\"px-2 border border-border-yellow rounded-l-full text-gray-light visited:text-gray-light hover:underline hover:bg-yellow-light\",\"children\":\"Intermediate\"}],[\"$\",\"a\",\"Dev\",{\"rel\":\"tag\",\"href\":\"/Tags/Dev\",\"className\":\"px-2 border border-border-yellow rounded-l-full text-gray-light visited:text-gray-light hover:underline hover:bg-yellow-light\",\"children\":\"Dev\"}],[\"$\",\"a\",\"Visual Studio\",{\"rel\":\"tag\",\"href\":\"/Tags/Visual-Studio\",\"className\":\"px-2 border border-border-yellow rounded-l-full text-gray-light visited:text-gray-light hover:underline hover:bg-yellow-light\",\"children\":\"Visual Studio\"}],[\"$\",\"a\",\"Windows\",{\"rel\":\"tag\",\"href\":\"/Tags/Windows\",\"className\":\"px-2 border border-border-yellow rounded-l-full text-gray-light visited:text-gray-light hover:underline hover:bg-yellow-light\",\"children\":\"Windows\"}],[\"$\",\"a\",\".NET\",{\"rel\":\"tag\",\"href\":\"/Tags/.NET\",\"className\":\"px-2 border border-border-yellow rounded-l-full text-gray-light visited:text-gray-light hover:underline hover:bg-yellow-light\",\"children\":\".NET\"}],[\"$\",\"a\",\"ASP.NET\",{\"rel\":\"tag\",\"href\":\"/Tags/ASP.NET\",\"className\":\"px-2 border border-border-yellow rounded-l-full text-gray-light visited:text-gray-light hover:underline hover:bg-yellow-light\",\"children\":\"ASP.NET\"}]]}],[\"$\",\"h1\",null,{\"className\":\"text-4xl text-text-gray\",\"children\":\"Adapting GRML\"}],[\"$\",\"div\",null,{\"className\":\"max-w-[600px]\",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex pt-4 justify-between\",\"children\":[[\"$\",\"div\",null,{\"className\":\"text-base hover:underline font-bold\",\"children\":[\"$\",\"$L3\",null,{\"href\":\"/script/Membership/View.aspx?mid=47237\",\"className\":\"text-gray-lightest\",\"children\":\"Toby Jacob Rhodes\"}]}],[\"$\",\"div\",null,{\"className\":\"flex items-center gap-2\",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex\",\"children\":[[\"$\",\"$L4\",\"0\",{\"src\":\"/icons/starIcon.png\",\"alt\":\"starIcon\",\"width\":24,\"height\":24}],[\"$\",\"div\",\"1\",{\"className\":\"relative\",\"children\":[[\"$\",\"$L4\",null,{\"src\":\"/icons/emptyStarIcon.png\",\"alt\":\"emptyStarIcon\",\"width\":24,\"height\":24}],[\"$\",\"div\",null,{\"className\":\"absolute left-0 top-0 overflow-hidden\",\"style\":{\"maxWidth\":\"54.545449999999995%\"},\"children\":[\"$\",\"$L4\",null,{\"src\":\"/icons/starIcon.png\",\"alt\":\"starIcon\",\"width\":24,\"height\":24}]}]]}],[\"$\",\"$L4\",\"2\",{\"src\":\"/icons/emptyStarIcon.png\",\"alt\":\"emptyStarIcon\",\"width\":24,\"height\":24}],[\"$\",\"$L4\",\"3\",{\"src\":\"/icons/emptyStarIcon.png\",\"alt\":\"emptyStarIcon\",\"width\":24,\"height\":24}],[\"$\",\"$L4\",\"4\",{\"src\":\"/icons/emptyStarIcon.png\",\"alt\":\"emptyStarIcon\",\"width\":24,\"height\":24}]]}],[\"$\",\"p\",null,{\"className\":\"text-sm\",\"children\":[\"1.55\",\"/5 (\",8,\" vote\",\"s\",\")\"]}]]}]]}],[\"$\",\"div\",null,{\"className\":\"flex pt-2 gap-4\",\"children\":[[\"$\",\"p\",null,{\"className\":\"text-gray-lightest text-[13px]\",\"children\":\"Sep 3, 2004\"}],null,[\"$\",\"p\",null,{\"className\":\"text-gray-lightest text-[13px]\",\"children\":[6,\" min read\"]}],[\"$\",\"div\",null,{\"className\":\"flex gap-1 items-center\",\"children\":[[\"$\",\"$L4\",null,{\"src\":\"/icons/viewsIcon.png\",\"alt\":\"viewsIcon\",\"width\":16,\"height\":16,\"className\":\"w-4 h-4\"}],[\"$\",\"p\",null,{\"className\":\"text-gray-lightest text-[13px] pl-0.5\",\"children\":97364}]]}],[\"$\",\"div\",null,{\"className\":\"flex gap-1 items-center\",\"children\":[[\"$\",\"$L4\",null,{\"src\":\"/icons/downloadIcon.png\",\"alt\":\"downloadIcon\",\"width\":16,\"height\":16,\"className\":\"w-4 h-4\"}],[\"$\",\"p\",null,{\"className\":\"text-gray-lightest text-[13px] pl-0.5\",\"children\":177}]]}]]}]]}],[\"$\",\"p\",null,{\"className\":\"pt-6 pb-4 text-gray-lightest\",\"children\":\"Convert a HTML web page to GRML.\"}],[\"$\",\"$L17\",null,{\"css\":\"$18\",\"children\":[\"$\",\"$L19\",null,{\"children\":[\"$\",\"div\",null,{\"className\":\"article\",\"dangerouslySetInnerHTML\":{\"__html\":\"$1a\"}}]}]}]]}],[\"$\",\"div\",null,{\"children\":[\"$\",\"$L5\",null,{\"adUnit\":\"/67541884/CPLargeSky160600\",\"adSlotId\":\"div-gpt-ad-1738591766860-0\",\"adSize\":[300,600],\"className\":\"mt-40 sticky top-40\"}]}]]}]\n"])</script></body></html>