Created
May 30, 2019 13:34
-
-
Save eduglez/8ee6086ca7761ddb0f954d6db5553b63 to your computer and use it in GitHub Desktop.
ServiceNow - Generate documentation in Markdown directly from the browser console
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(){ | |
var text = ""; | |
var printl = function(str){ | |
text = text + str + '\n'; | |
}; | |
var println = function(str) { | |
if(str){ | |
text = text + str + '\n\n'; | |
}else{ | |
text = text + '\n'; | |
} | |
}; | |
var parseUrl = function(url) { | |
var currentUrl = ''; | |
if(url.indexOf('/') < 1){ | |
currentUrl = url; | |
}else{ | |
currentUrl = (new URL(url)).searchParams.get('uri') || url.substring(url.lastIndexOf('/')); | |
currentUrl = decodeURI(currentUrl); | |
} | |
currentUrl = currentUrl.substring(currentUrl.indexOf('/')+1); | |
var tableName = currentUrl.substring(0, currentUrl.indexOf(".do")); | |
var query; | |
if(tableName.endsWith('_list')){ | |
tableName = tableName.substring(0, tableName.lastIndexOf('_list')); | |
query = (new URL('http://fakeorigin/'+currentUrl)).searchParams.get('sysparm_query'); | |
}else{ | |
query = 'sys_id='+(new URL('http://fakeorigin/'+currentUrl)).searchParams.get('sys_id'); | |
} | |
return {table: tableName, query: query}; | |
}; | |
var docu = {}; | |
var UI_TYPE = { | |
'0': 'Desktop', | |
'1': 'Mobile / Service Portal', | |
'10': 'All' | |
}; | |
var TEMPLATE = { | |
'sys_ui_policy': { | |
'header': function(element) { | |
println('# UI Policies'); | |
println('<https://docs.servicenow.com/bundle/madrid-platform-administration/page/administer/form-administration/task/t_CreateAUIPolicy.html>'); | |
println('UI policies dynamically change the behavior of information on a form and control custom process flows for tasks.'); | |
println('For example, you can use UI policies to make the number field on a form read-only, make the short description field mandatory, and hide other fields. Basic UI policies do not require any scripting, however for more advanced actions, use the Run scripts option.'); | |
println('You can also use client scripts to perform all of these actions, but for faster load times use UI policies when possible.'); | |
}, | |
'content': function(element) { | |
println('## ' + element.short_description); | |
println(element.description); | |
println('### UI Policy main fields'); | |
println('**<span title="The active status of the UI policy. Only active UI policies are applied.">Active</span>:** ' + element.active); | |
println('**Table:** ' + element.table); | |
println('**Order:** ' + element.order); | |
println('### When to Apply'); | |
println('**Conditions:** ``' + element.conditions + '``'); | |
println('**Global:** ' + element.global); | |
println('**View:** ' + element.view); | |
println('**Reverse if false:** ' + element.reverse_if_false); | |
println('**On load:** ' + element.on_load); | |
println('**Inherit:** ' + element.inherit); | |
println('### Script'); | |
println('**Run Scripts:** ' + element.run_scripts); | |
if(element.run_scripts == 'true'){ | |
println('**Execute if true:**' + "\n" + "```javascript\n" + element.script_true + "\n```"); | |
println('**Execute if false:**' + "\n" + "```javascript\n" + element.script_false + "\n```"); | |
} | |
println('### Other fields'); | |
println('**Run scripts in UI type:** ' + UI_TYPE[element.ui_type]); | |
println('### UI Policy Actions'); | |
printl('Table|Field name|Mandatory|Visible|Read Only|Clear the field value'); | |
printl('---|---|---|---|---') | |
docu['sys_ui_policy_action'] | |
.filter( | |
function(el){ | |
return el.ui_policy == element.sys_id; | |
} | |
) | |
.forEach( | |
function(el){ | |
printl(el.table + "|" + el.field + "|" + el.mandatory + "|" + el.visible + "|" + el.disabled + "|" + el.cleared); | |
} | |
); | |
println(); | |
println('### JSON UI Policy Raw definition'); | |
println("```javascript\n" + JSON.stringify(element, null, 2) + "\n```"); | |
docu['sys_ui_policy_action'] | |
.filter( | |
function(el){ | |
return el.ui_policy == element.sys_id; | |
} | |
) | |
.forEach( | |
function(el){ | |
println("#### UI Policy Action: **" + el.table + "." + el.field + "**"); | |
println("```javascript\n" + JSON.stringify(el, null, 2) + "\n```"); | |
} | |
); | |
}, | |
'footer': function(element) { | |
}, | |
}, | |
'sys_script_client': { | |
'header': function(element) { | |
println('# Client Scripts'); | |
println('<https://docs.servicenow.com/bundle/madrid-application-development/page/script/client-scripts/concept/client-scripts.html>'); | |
println('Client scripts allow the system to run JavaScript on the client (web browser) when client-based events occur, such as when a form loads, after form submission, or when a field changes value.'); | |
}, | |
'content': function(element) { | |
println('## ' + element.name); | |
println(element.description); | |
println('**Type:** ' + element.type); | |
println('**Table:** ' + element.table); | |
println("**Script:**" + "\n" + "```javascript\n" + element.script + "\n```"); | |
}, | |
'footer': function(element) { | |
} | |
}, | |
'sys_security_acl': { | |
'header': function(element) { | |
println('# Access control list rules (ACL)'); | |
println('<https://docs.servicenow.com/bundle/london-platform-administration/page/administer/contextual-security/concept/access-control-rules.html>'); | |
println('Rules for access control lists (ACLs) restrict access to data by requiring users to pass a set of requirements before they can interact with it.'); | |
}, | |
'content': function(element) { | |
println('## ' + element.name); | |
println(element.description); | |
var roles = docu['sys_security_acl_role'] | |
.filter(function(el){ | |
return el.sys_security_acl == element.sys_id; | |
}) | |
.reduce(function(allRoles, role){ | |
if(allRoles == "") | |
return role.dv_sys_user_role; | |
else | |
return allRoles + ", " + role.dv_sys_user_role; | |
}, ""); | |
println("**Roles:** " + roles); | |
println("**Operation:** " + element.operation); | |
println("**Condition:** " + element.condition); | |
println("**Script:**" + "\n" + "```javascript\n" + element.script + "\n```"); | |
}, | |
'footer': function(element) { | |
} | |
}, | |
'sys_ui_action': { | |
'header': function(element) { | |
println('# UI Actions'); | |
println('<https://docs.servicenow.com/bundle/madrid-platform-administration/page/administer/list-administration/concept/c_UIActions.html>'); | |
println('UI actions include the buttons, links, and context menu items on forms and lists. Configure UI actions to make the UI more interactive, customized, and specific to user activities.'); | |
}, | |
'content': function(element) { | |
println('## '+ element.name); | |
println(element.comments); | |
println("**Tabla:** " + element.table); | |
println("**Condición:** " + element.condition); | |
println("**Script:**" + "\n" + "```javascript\n" + element.script + "\n```"); | |
}, | |
'footer': function(element) { | |
} | |
}, | |
'sys_ui_page': { | |
'header': function(element) { | |
println('# UI Pages'); | |
println('<https://docs.servicenow.com/bundle/madrid-application-development/page/script/server-scripting/reference/r_UIPages.html>'); | |
println('UI pages can be used to create and display forms, dialogs, lists and other UI components.'); | |
}, | |
'content': function(element) { | |
println('## ' + element.name); | |
println(element.description); | |
println("**HTML:**" + "\n" + "```xml\n" + element.html + "\n```"); | |
println("**Client script:**" + "\n" + "```javascript\n" + element.client_script + "\n```"); | |
println("**Processing script:**" + "\n" + "```javascript\n" + element.processing_script + "\n```"); | |
}, | |
'footer': function(element) { | |
} | |
}, | |
'sys_script_include': { | |
'header': function(element) { | |
println('# Script Includes'); | |
println('<https://docs.servicenow.com/bundle/madrid-application-development/page/script/server-scripting/concept/c_ScriptIncludes.html>'); | |
println('Script includes are used to store JavaScript that runs on the server.'); | |
println('Create script includes to store JavaScript functions and classes for use by server scripts. Each script include defines either an object class or a function.'); | |
println('Consider using script includes instead of global business rules because script includes are only loaded on request.'); | |
}, | |
'content': function(element) { | |
println('## ' + element.name); | |
println(element.description); | |
println("**Script:**" + "\n" + "```javascript\n" + element.client_script + "\n```"); | |
}, | |
'footer': function(element) { | |
} | |
}, | |
'sys_data_source': { | |
'header': function(element) { | |
println('# Data Sources'); | |
println('<https://docs.servicenow.com/bundle/madrid-platform-administration/page/administer/import-sets/concept/c_DataSources.html>'); | |
println('Data sources are used to create an import set so that data can be processed, if necessary, prior to being mapped onto a production table.'); | |
}, | |
'content': function(element) { | |
println('## ' + element.name); | |
println("**Import set table:** " + element.import_set_table_name); | |
println("**Type:** " + element.type); | |
println("**Format:** " + element.format); | |
println("**File retrievel method:** " + element.file_retrieval_method); | |
}, | |
'footer': function(element) { | |
} | |
}, | |
'sys_transform_map': { | |
'header': function(element) { | |
println('# Transform Maps'); | |
println('<https://docs.servicenow.com/bundle/madrid-platform-administration/page/script/server-scripting/concept/c_CreatingNewTransformMaps.html>'); | |
println('A transform map is a set of field maps that determine the relationships between fields in an import set and fields in an existing ServiceNow table, such as Incident [incident] or User [sys_user].'); | |
}, | |
'content': function(element) { | |
println('## ' + element.name); | |
println("**Source table:** " + element.source_table); | |
println("**Tabla destino:** " + element.target_table); | |
}, | |
'footer': function(element) { | |
} | |
}, | |
'sys_script': { | |
0: function(element) { | |
println('## Business Rule: ' + element.name); | |
println("**Description:** " + element.description); | |
println("**Table:** " + element.collection); | |
println("**When:** " + element.when); | |
println("**Filter condition:** " + element.filter_condition); | |
println("**Condition:** " + element.condition); | |
println("**Script:**" + "\n" + "```javascript\n" + element.script + "\n```"); | |
} | |
}, | |
'sys_db_object': { | |
0: function(element) { | |
println('## Tabla: ' + element.label); | |
println("**Name:** " + element.name); | |
println("**Extends:** " + element.super_class); | |
} | |
}, | |
'sys_properties': { | |
0: function(element) { | |
println('## System property: ' + element.name); | |
println(element.description); | |
println("**Value:** " + element.value); | |
} | |
}, | |
'sysevent_script_action': { | |
0: function(element) { | |
println('## Script Action: ' + element.name); | |
println("**Event name:**" + element.event_name); | |
println("**Condition Script:** " + element.condition_script); | |
println("**Script:**" + "\n" + "```javascript\n" + element.script + "\n```"); | |
} | |
}, | |
}; // var printers | |
var currentUrl = (new URL(window.location.href)).searchParams.get('uri') || window.location.href.substring(window.location.href.lastIndexOf('/')); | |
// What I need is a bunch of relative links | |
var bookmarks = jQuery | |
.ajax({type: "GET", url: "sys_ui_bookmark_list.do?sysparm_query=titleSTARTSWITHMicro%20-&JSONv2&sysparm_action=getRecords", async: false}) | |
.responseJSON | |
.records | |
.map(function(el){ | |
return el.url; | |
}); | |
bookmarks | |
.forEach(function(bookmark){ | |
var tableName = bookmark.substring(0, bookmark.indexOf(".do")-5); | |
docu[tableName] = jQuery.ajax({type: "GET", url: bookmark+"&JSONv2&sysparm_action=getRecords&displayvalue=all", async: false}).responseJSON.records; | |
}); | |
['sys_ui_policy', 'sys_security_acl', 'sys_script_client', 'sys_ui_action', 'sys_ui_page', 'sys_script_include','sys_data_source', 'sys_transform_map'] | |
.forEach(function(table_name){ | |
TEMPLATE[table_name]['header'](); | |
docu[table_name] | |
.forEach(function(el){ | |
TEMPLATE[table_name]['content'](el); | |
}); | |
TEMPLATE[table_name]['footer'](); | |
}); | |
jQuery('body').append('\ | |
<div class="modal fade" id="docModal" tabindex="-1" role="dialog" aria-labelledby="docModalLabel">\ | |
<div class="modal-dialog" role="document">\ | |
<div class="modal-content">\ | |
<div class="modal-header">\ | |
<button type="button" class="close" data-dismiss="modal" aria-label="Close">\ | |
<span aria-hidden="true">×</span>\ | |
</button>\ | |
<h4 class="modal-title" id="docModalLabel">Copy documentation</h4>\ | |
</div>\ | |
<div class="modal-body">\ | |
<textarea id="docModalTextArea" rows="20" class="form-control"></textarea>\ | |
</div>\ | |
<div class="modal-footer">\ | |
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>\ | |
<button type="button" class="btn btn-primary" onclick="document.getElementById(\'docModalTextArea\').select();document.execCommand(\'copy\');">Copy content</button>\ | |
</div>\ | |
</div>\ | |
</div>\ | |
</div>\ | |
'); | |
jQuery('#docModalTextArea').text(text); | |
jQuery('#docModal').modal('show'); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment