Skip to content

Commit e09bdcc

Browse files
committed
add support for markdown uri and llms.txt file
1 parent 7ae3099 commit e09bdcc

File tree

6 files changed

+236
-5
lines changed

6 files changed

+236
-5
lines changed

Application.cfc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
<cfparam name="request.cacheControlMaxAge" default="604800" type="integer">
5151
<cfheader name="Cache-Control" value="public, max-age=#Int(request.cacheControlMaxAge)#">
5252
<cfif len(showError)><cfoutput>#showError#</cfoutput><cfflush></cfif>
53-
<cfcontent reset="true" type="text/html"><cfinclude template="views/layout.cfm">
53+
<cfinclude template="views/layout.cfm">
5454
</cffunction>
5555

5656
<cffunction name="linkTo" output="false">
@@ -149,7 +149,7 @@
149149
</div>
150150
</cfsavecontent>
151151

152-
<cfcontent reset="true" type="text/html"><cfheader statuscode="500" statustext="Server Error"><cfinclude template="views/layout.cfm">
152+
<cfcontent reset="true" type="text/html"><cfheader statuscode="500"><cfinclude template="views/layout.cfm">
153153
</cffunction>
154154

155155
</cfcomponent>

doc.cfm

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<cfparam name="url.name" default="cfquery">
2+
<cfparam name="url.format" default="html">
23
<cfset request.unsafe_name = url.name>
34
<cfset url.name = ReReplace(url.name, "[^a-zA-Z0-9_-]", "", "ALL")>
45
<cfif url.name IS "index">
@@ -11,7 +12,10 @@
1112
<!--- convert md to HTML --->
1213
<cfset flexmark = new lib.Processor() >
1314
<cfset path = (url.name is "how-to-contribute" ? 'CONTRIBUTING' : './guides/en/#url.name#')>
14-
<cfset data = flexmark.toHTML(FileRead(ExpandPath("#path#.md")))>
15+
<cfset data = FileRead(ExpandPath("#path#.md"))>
16+
<cfif url.format IS "html">
17+
<cfset data = flexmark.toHTML(data)>
18+
</cfif>
1519
<cfset request.gitFilePath = "/tree/master/guides/en/"&(url.name is "how-to-contribute" ? 'CONTRIBUTING' : url.name)&".md">
1620
<cfcatch>
1721
<cfset data = "Error processing markdown: #encodeForHTML(cfcatch.message)# #encodeForHTML(cfcatch.detail)#">
@@ -63,7 +67,15 @@
6367
<cfif data.keyExists("description")>
6468
<cfset request.description = data.description>
6569
</cfif>
66-
<cfinclude template="views/doc.cfm">
70+
<cfif url.format IS "md">
71+
<cfinclude template="views/doc-md.cfm">
72+
<cfheader name="Link" value="<https://cfdocs.org/#url.name#>; rel=""canonical""">
73+
<cfelse>
74+
<cfinclude template="views/doc.cfm">
75+
<cfheader name="Link" value="<https://cfdocs.org/#url.name#.md>; rel=""alternate""; type=""text/markdown""">
76+
</cfif>
77+
<cfelseif url.format IS "md">
78+
<cfinclude template="views/doc-md.cfm">
6779
<cfelse>
6880
<cfinclude template="views/markdown.cfm">
6981
</cfif>

llms.cfm

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<cfsetting enablecfoutputonly="true">
2+
<cfset request.skiplayout = true>
3+
<cfset tags = deserializeJSON(fileRead(expandPath("data/en/tags.json")))>
4+
<cfcontent reset="true" type="text/markdown"><cfoutput>## CFDocs ColdFusion / CFML Documentation
5+
6+
The [cfdocs.org](https://cfdocs.org/) or "cfdocs" repository is a community powered
7+
documentation guide for Adobe ColdFusion programming language, also known as CFML.
8+
9+
"CF" is an abbreviation for "ColdFusion".
10+
11+
You should not use a space between "Cold Fusion", you should say it as one word: "ColdFusion" with the F in uppercase. These days
12+
ColdFusion tends to refer to the Adobe ColdFusion runtime engine, while CFML is often used to refer to the language (which can run on multiple runtimes including ColdFusion).
13+
14+
#### Background Information
15+
16+
The cfdocs website was created in 2004 by ColdFusion and Web Application Security Expert [Pete Freitag](https://www.petefreitag.com/). The project is primarily sponsored by
17+
his company [Foundeo Inc.](https://foundeo.com/) which provides consulting services and security products (such as Fixinator a CFML code security scanner, FuseGuard a CFML WAF, and HackMyCF a server security scanner) for CFML developers.
18+
There are also over 175 community contributors who have contributed to the documentation since 2013 when community contributions were first accepted.
19+
20+
The original motivation for the project was to provide better and faster access to the CFML documentation. While cfdocs still remains a fast and trusted source of information, it
21+
has also become useful to compare support for various tags and functions across different versions and engines.
22+
23+
Several CFML IDE Plugins now use the cfdocs dataset to provide inline code editing assistance, and documentation.
24+
25+
CFDocs provides documentation for several CFML engines or language runtimes that
26+
can execute the CFML programming language: Adobe ColdFusion (ACF), Lucee (forked from Railo), and BoxLang.
27+
BlueDragon or OpenBD are no longer supported because they are not under active development.
28+
29+
When you see something like "CF11+" that means that it is supported on Adobe ColdFusion version 11 and up.
30+
If you see Lucee6+ that means it is supported as of Lucee version 6 and above.
31+
32+
The CFML language provides several built-in tags, and built-in functions. Some CF developers call the built-in functions "BIF's". There are sometimes implementation differences between runtime engines, which is one of the reasons that cfdocs.org is a useful
33+
reference.
34+
35+
#### URL Structure
36+
37+
The URI for a doc page will match the name of a CFML tag, or CFML BIF, for example cfquery will be located at https://cfdocs.org/cfquery
38+
39+
Machine or LLM markdown versions of the URL can be found by appending .md to the URI, for example https://cfdocs.org/cfquery.md
40+
41+
Remove the .md for a human readable HTML version of the page.
42+
43+
#### CFML Tags
44+
45+
The following are tags which are built-in on ColdFusion:
46+
47+
<cfloop array="#application.index.tags#" index="f">- [#f#](https://cfdocs.org/#f#.md)
48+
</cfloop>
49+
50+
#### CFML Functions
51+
52+
The following functions are built-in on ColdFusion and can be used anywhere in CFML code:
53+
54+
<cfloop array="#application.index.functions#" index="f">- [#f#](https://cfdocs.org/#f#.md)
55+
</cfloop>
56+
57+
#### CFML Categories
58+
59+
<cfloop array="#application.index.categories#" index="f">- [#f#](https://cfdocs.org/#f#.md)
60+
</cfloop>
61+
62+
#### CFML Guides
63+
64+
<cfloop array="#application.index.guides#" index="f">- [<cfif application.guides.keyExists(f)>#application.guides[f]#<cfelse>#f#</cfif>](https://cfdocs.org/#f#.md)
65+
</cfloop>
66+
67+
</cfoutput>
68+
<cfheader name="Link" value="<https://cfdocs.org/llms.txt>; rel=""canonical""">

rewrites.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,19 @@
44
<from>^/try/([^./]+)/([0-9]+)/?$</from>
55
<to>/trycf.cfm?name=$1&amp;index=$2</to>
66
</rule>
7+
<rule>
8+
<from>^/llms.txt$</from>
9+
<to last="true">/llms.cfm</to>
10+
</rule>
11+
<rule>
12+
<from>^/([^./]+)\.md$</from>
13+
<to last="true">/doc.cfm?name=$1&amp;format=md</to>
14+
</rule>
715
<rule>
816
<from>^/([^./]+)$</from>
917
<to>/doc.cfm?name=$1</to>
1018
</rule>
19+
1120
<rule>
1221
<from>^/tag-summary$</from>
1322
<to type="redirect">/tags</to>

views/doc-md.cfm

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
<cfparam name="url.name" default="">
2+
<cfset url.name = ReReplace(url.name, "[^a-zA-Z0-9_-]", "", "ALL")>
3+
<cfsetting enablecfoutputonly="true">
4+
<cfset request.skiplayout = true>
5+
<cfcontent reset="true" type="text/markdown">
6+
<cfif isStruct(data)>
7+
8+
<cfif data.keyExists("type") AND data.type IS "tag">
9+
<cfif StructKeyExists(data, "script")>
10+
<cfset data.scriptTitle = "Script Syntax">
11+
<cfelseif data.keyExists("syntax") AND NOT ListFindNoCase("cfif,cfset,cfelse,cfelseif,cfloop,cfinclude,cfparam,cfswitch,cfcase,cftry,cfthrow,cfrethrow,cfcatch,cffinally,cfmodule,cfcomponent,cfinterface,cfproperty,cffunction,cfimport,cftransaction,cftrace,cflock,cfthread,cfsavecontent,cflocation,cfargument,cfapplication,cfscript", data.name)>
12+
<!--- add cfscript syntax --->
13+
<cfset data.script = replaceScript(name = data.name, syntax = data.syntax, mode = "other")>
14+
<cfset data.scriptTitle = "Script Syntax ACF11+, Lucee">
15+
</cfif>
16+
</cfif>
17+
18+
<cfoutput>## #data.name#
19+
20+
<cfif data.keyExists("description")>#data.description#</cfif>
21+
22+
<cfif data.keyExists("discouraged")>
23+
#### Discouraged
24+
25+
#data.discouraged#
26+
27+
</cfif>
28+
29+
<cfif StructKeyExists(data, "syntax") AND Len(data.syntax)>
30+
###### Syntax
31+
32+
```
33+
#trim(Replace(data.syntax, Chr(10), "<br>", "ALL"))# <cfif data.type IS "function" AND StructKeyExists(data, "returns") AND Len(data.returns)>returns #encodeForHTML(data.returns)#</cfif>
34+
```
35+
36+
</cfif>
37+
<cfif data.type IS "tag" AND StructKeyExists(data, "script")>
38+
######## #data.scriptTitle#
39+
40+
```
41+
#data.script#
42+
```
43+
44+
<cfelseif data.type is "function" AND StructKeyExists(data, "member")>
45+
######## Member Function Syntax
46+
47+
```
48+
#data.member# <cfif StructKeyExists(data, "member_details") AND StructKeyExists(data.member_details, "returns") && Len(data.member_details.returns)> returns #encodeForHTML(data.member_details.returns)#</cfif>
49+
```
50+
</cfif>
51+
52+
<cfif StructKeyExists(data, "params") AND ArrayLen(data.params)>
53+
54+
#### <cfif data.type IS "tag">Attribute Reference<cfelseif data.type IS "function">Argument Reference<cfelseif len(trim(data.name))>#data.name#</cfif>
55+
<cfset hasCallbackParams = false>
56+
| Name | Type | Required | Default | Description | Values |
57+
| --- | --- | --- | --- | --- | --- |<cfloop array="#data.params#" index="p">
58+
| <cfif p.keyExists("name")>#EncodeForMarkdownCell(p.name)#</cfif> | <cfif p.keyExists("type")>#EncodeForMarkdownCell(p.type)#</cfif> | <cfif p.keyExists("required") AND isBoolean(p.required) AND p.required>Yes<cfelse>No</cfif> | <cfif p.keyExists("default")>#EncodeForMarkdownCell(p.default)#</cfif> | <cfif p.keyExists("description")>#EncodeForMarkdownCell(p.description)#</cfif><cfif structKeyExists(p, "callback_params") AND isArray(p.callback_params) and not arrayIsEmpty(p.callback_params)><cfset hasCallbackParams = true><br>See callback arguments below.</cfif> | <cfif structKeyExists(p, "values") AND isArray(p.values) AND arrayLen(p.values)>#EncodeForMarkdownCell(arrayToList(p.values))#</cfif> |</cfloop>
59+
60+
<cfif hasCallbackParams>
61+
<cfloop array="#data.params#" index="p"><cfif structKeyExists(p, "callback_params") AND isArray(p.callback_params) and not arrayIsEmpty(p.callback_params)>
62+
###### #p.name# Callback Arguments
63+
64+
| Name | Type | Required | Description |
65+
| --- | --- | --- | --- |
66+
<cfloop array="#p.callback_params#" index="cp">| #cp.name# | #cp.type# | <cfif cp.keyExists("required") AND isBoolean(cp.required) AND cp.required>Yes<cfelse>No</cfif> | #EncodeForMarkdownCell(cp.description)# |
67+
</cfloop></cfif></cfloop>
68+
</cfif>
69+
</cfif>
70+
71+
<cfif data.keyExists("engines") AND isStruct(data.engines)>
72+
#### CFML Engine Support
73+
74+
The #data.name# <cfif data.type IS "tag">tag<cfelseif data.type IS "function">function</cfif> is supported on the following CFML engines:
75+
76+
| Engine | Minimum Version | Notes |
77+
| --- | --- | --- |
78+
<cfloop list="ColdFusion,Lucee,BoxLang" index="engine"><cfif data.engines.keyExists(engine) AND data.engines[engine].keyExists("docs") AND len(data.engines[engine].docs)>| #engine# | <cfif data.engines[engine].keyExists("minimum_version")>#EncodeForMarkdownCell(data.engines[engine].minimum_version)#</cfif> | <cfif data.engines[engine].keyExists("notes")>#EncodeForMarkdownCell(data.engines[engine].notes)#</cfif> |
79+
</cfif></cfloop>
80+
</cfif>
81+
82+
<cfif StructKeyExists(data, "examples") AND IsArray(data.examples) AND ArrayLen(data.examples)>
83+
#### Examples
84+
85+
<cfloop array="#data.examples#" index="ex">
86+
###### #ex.title#
87+
88+
#ex.description#
89+
90+
```
91+
#ex.code#
92+
```
93+
<cfif StructKeyExists(ex, "result") AND Len(Trim(ex.result))>Expected Result: #Trim(ex.result)#</cfif>
94+
95+
</cfloop>
96+
</cfif>
97+
98+
<cfif StructKeyExists(data, "related") AND IsArray(data.related) AND ArrayLen(data.related)>
99+
#### Related Tags and Functions
100+
101+
<cfloop array="#data.related#" index="rel">[#rel#](https://cfdocs.org/#rel#.md)
102+
</cfloop>
103+
</cfif>
104+
105+
</cfoutput>
106+
<cfelse>
107+
<cfoutput>#data#</cfoutput>
108+
</cfif>
109+
110+
<cfoutput>
111+
The human version of this document can be found here: [https://cfdocs.org/#url.name#](https://cfdocs.org/#url.name#) which is part of the cfdocs.org repository. Project created by [Pete Freitag](https://www.petefreitag.com) and sponsored by [Foundeo Inc.](https://foundeo.com/)
112+
</cfoutput>
113+
114+
<cffunction name="EncodeForMarkdownCell" output="false">
115+
<cfargument name="value" type="string" required="true">
116+
<cfset var result = ARGUMENTS.value>
117+
<cfset result = replace(result, "|", " ", "ALL")>
118+
<cfset result = ReReplace(result, "\r?\n", "<br />", "ALL")>
119+
<cfreturn result>
120+
</cffunction>
121+
122+
<cffunction name="replaceScript">
123+
<cfargument name="name" type="string" required="true">
124+
<cfargument name="mode" type="string" required="true">
125+
<cfargument name="syntax" type="string">
126+
127+
<cfset var result = "">
128+
129+
<cfif mode is "cf">
130+
<cfset result = ReplaceNoCase(name, "cf", "") & ";">
131+
<cfelseif mode is "other">
132+
<!--- add cfscript syntax --->
133+
<cfset result = ReReplace(syntax, "[<\r\n]", "", "ALL")>
134+
<cfset result = ReplaceNoCase(result, name, name & "(")>
135+
<cfset result = Replace(result, "( ", "(")>
136+
<!--- replace double quote followed by a space with a ,[space] --->
137+
<cfset result = ReReplace(result, """ ", """, ", "ALL")>
138+
<cfset result = ReReplace(result, ",? ?>", ");")>
139+
</cfif>
140+
<cfreturn result>
141+
</cffunction>

views/layout.cfm

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
<cfif StructKeyExists(request, "skiplayout") AND request.skiplayout><cfoutput>#request.content#</cfoutput><cfelse><!DOCTYPE html>
1+
<cfif StructKeyExists(request, "skiplayout") AND request.skiplayout><cfoutput>#request.content#</cfoutput><cfelse>
2+
<cfcontent reset="true" type="text/html"><!DOCTYPE html>
23
<html lang="en">
34
<head>
45
<meta charset="utf-8">

0 commit comments

Comments
 (0)