Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F1429019
SourceHandler.js
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
SourceHandler.js
View Options
const
Model
=
require
(
'./Model.js'
);
/**
* TemplateData Source Handler
*
* Loads and validates the templatedata and template parameters
* whether in the page itself or from its parent.
*
* @class
* @extends OO.EventEmitter
*
* @constructor
* @param {Object} [config]
* @param {string} [config.fullPageName=""] The full name of the current page
* @param {string} [config.parentPage=""] The name of the parent page
* @param {string} [config.isPageSubLevel=false] The page is sub-level of another template
*/
function
SourceHandler
(
config
)
{
config
=
config
||
{};
// Mixin constructors
OO
.
EventEmitter
.
call
(
this
);
this
.
apiCache
=
{};
this
.
templateSourceCodePromise
=
null
;
this
.
templateSourceCodeParams
=
[];
// Config
this
.
setParentPage
(
config
.
parentPage
);
this
.
setPageSubLevel
(
config
.
isPageSubLevel
);
this
.
setFullPageName
(
config
.
fullPageName
);
}
/* Inheritance */
OO
.
mixinClass
(
SourceHandler
,
OO
.
EventEmitter
);
/**
* Get information from the MediaWiki API
*
* @param {string} page Page name
* @param {boolean} [getTemplateData] Fetch the templatedata in the page.
* @return {jQuery.Promise} API promise
*/
SourceHandler
.
prototype
.
getApi
=
function
(
page
,
getTemplateData
)
{
const
type
=
getTemplateData
?
'templatedata'
:
'query'
,
api
=
new
mw
.
Api
(),
baseConfig
=
{
action
:
type
,
titles
:
page
,
redirects
:
getTemplateData
?
1
:
0
};
let
config
;
if
(
type
===
'query'
)
{
config
=
Object
.
assign
(
baseConfig
,
{
prop
:
'revisions'
,
rvprop
:
'content'
,
indexpageids
:
'1'
}
);
}
// Cache
if
(
!
this
.
apiCache
[
page
]
||
!
this
.
apiCache
[
page
][
type
]
)
{
this
.
apiCache
[
page
]
=
this
.
apiCache
[
page
]
||
{};
this
.
apiCache
[
page
][
type
]
=
api
.
get
(
config
);
}
return
this
.
apiCache
[
page
][
type
];
};
/**
* Go over the current wikitext and build a new model.
*
* @param {string} [wikitext] Source of the template.
* @return {jQuery.Promise} Promise resolving into a new Model
* or is rejected if the model was impossible to create.
*/
SourceHandler
.
prototype
.
buildModel
=
function
(
wikitext
)
{
const
templateDataString
=
this
.
findModelInString
(
wikitext
);
let
tdObject
=
null
;
if
(
templateDataString
!==
null
)
{
try
{
tdObject
=
JSON
.
parse
(
templateDataString
);
}
catch
(
err
)
{
// The json object is invalid. There's no need to continue.
return
$
.
Deferred
().
reject
();
}
}
// Get parameters from source code
// Mostly used for the import option
return
this
.
getParametersFromTemplateSource
(
wikitext
)
// This is always successful by definition
.
then
(
(
templateSourceCodeParams
)
=>
Model
.
static
.
newFromObject
(
tdObject
,
templateSourceCodeParams
)
);
};
/**
* Retrieve parameters from the template code from source in this order:
*
* 1. Check if there's a template in the given 'wikitext' parameter. If not,
* 2. Check if there's a template in the current page. If not,
* 3. Check if the page is a subpage and go up a level to check for template code. If none found,
* 4. Repeat until we are in the root of the template
* 5. Save the name of the page where the template is taken from
*
* Cache the templateCodePromise so we don't have to do this all over again on each
* template code request.
*
* @param {string} [wikitext] Optional. Source of the template.
* @return {jQuery.Promise} Promise resolving into template parameter array
*/
SourceHandler
.
prototype
.
getParametersFromTemplateSource
=
function
(
wikitext
)
{
let
params
=
[];
if
(
!
this
.
templateSourceCodePromise
)
{
// Check given page text first
if
(
wikitext
)
{
params
=
this
.
extractParametersFromTemplateCode
(
wikitext
);
}
if
(
params
.
length
>
0
)
{
// There are parameters found; Resolve.
this
.
templateSourceCodePromise
=
$
.
Deferred
().
resolve
(
params
);
}
else
if
(
this
.
isPageSubLevel
()
&&
this
.
getParentPage
()
)
{
// Get the content of the parent
this
.
templateSourceCodePromise
=
this
.
getApi
(
this
.
getParentPage
()
).
then
(
(
resp
)
=>
{
let
pageContent
=
''
;
// Verify that we have a sane response from the API.
// This is particularly important for unit tests, since the
// requested page from the API is the Qunit module and has no content
if
(
resp
.
query
.
pages
[
resp
.
query
.
pageids
[
0
]
].
revisions
&&
resp
.
query
.
pages
[
resp
.
query
.
pageids
[
0
]
].
revisions
[
0
]
)
{
pageContent
=
resp
.
query
.
pages
[
resp
.
query
.
pageids
[
0
]
].
revisions
[
0
][
'*'
];
}
return
this
.
extractParametersFromTemplateCode
(
pageContent
);
},
// Resolve an empty parameters array
()
=>
$
.
Deferred
().
resolve
(
[]
)
);
}
else
{
// No template found. Resolve to empty array of parameters
this
.
templateSourceCodePromise
=
$
.
Deferred
().
resolve
(
[]
);
}
}
return
this
.
templateSourceCodePromise
;
};
/**
* Retrieve template parameters from the template code.
*
* Adapted from https://he.wikipedia.org/wiki/MediaWiki:Gadget-TemplateParamWizard.js
*
* @param {string} templateCode Source of the template.
* @return {string[]} An array of parameters that appear in the template code
*/
SourceHandler
.
prototype
.
extractParametersFromTemplateCode
=
function
(
templateCode
)
{
const
paramNames
=
[],
normalizedParamNames
=
[],
// This regex matches the one in TemplateDataBlob.php
paramExtractor
=
/{{{+([^\n#={|}]*?)([<|]|}}})/mg
;
// Ignore non-wikitext content in comments and wikitext-escaping tags
templateCode
=
templateCode
.
replace
(
/<!--[\s\S]*?-->/g
,
''
)
.
replace
(
/<nowiki\s*>[\s\S]*?<\/nowiki\s*>/g
,
''
)
.
replace
(
/<pre\s*>[\s\S]*?<\/pre\s*>/g
,
''
);
let
matches
;
while
(
(
matches
=
paramExtractor
.
exec
(
templateCode
)
)
!==
null
)
{
// This normalization process is repeated in PHP in TemplateDataBlob.php
const
normalizedParamName
=
matches
[
1
].
replace
(
/[-_ ]+/
,
' '
).
trim
().
toLowerCase
();
if
(
!
normalizedParamName
||
normalizedParamNames
.
indexOf
(
normalizedParamName
)
!==
-
1
)
{
continue
;
}
if
(
paramNames
.
indexOf
(
matches
[
1
]
)
===
-
1
)
{
normalizedParamNames
.
push
(
normalizedParamName
);
paramNames
.
push
(
matches
[
1
].
trim
()
);
}
}
return
paramNames
;
};
/**
* Look for a templatedata json string and return it, if it exists.
*
* @param {string} templateDataString Wikitext templatedata string
* @return {string|null} The isolated json string. Empty if no
* templatedata string was found.
*/
SourceHandler
.
prototype
.
findModelInString
=
function
(
templateDataString
)
{
const
parts
=
templateDataString
.
match
(
/<templatedata>([\s\S]*?)<\/templatedata>/i
);
if
(
parts
&&
parts
[
1
]
&&
parts
[
1
].
trim
().
length
>
0
)
{
return
parts
[
1
].
trim
();
}
else
{
return
null
;
}
};
/**
* Set the page as a sub page of the main template
*
* @param {boolean} [isSubLevel=false] Page is sublevel
*/
SourceHandler
.
prototype
.
setPageSubLevel
=
function
(
isSubLevel
)
{
this
.
subLevel
=
!!
isSubLevel
;
};
/**
* Set the page as a sub page of the main template
*
* @return {boolean} Page is sublevel
*/
SourceHandler
.
prototype
.
isPageSubLevel
=
function
()
{
return
this
.
subLevel
;
};
/**
* Get full page name
*
* @param {string} [pageName=""] Page name
*/
SourceHandler
.
prototype
.
setFullPageName
=
function
(
pageName
)
{
this
.
fullPageName
=
pageName
||
''
;
};
/**
* Get page full name
*
* @return {string} Page full name
*/
SourceHandler
.
prototype
.
getFullPageName
=
function
()
{
return
this
.
fullPageName
;
};
/**
* Set parent page
*
* @param {string} [parent=""] Parent page
*/
SourceHandler
.
prototype
.
setParentPage
=
function
(
parent
)
{
this
.
parentPage
=
parent
||
''
;
};
/**
* Get parent page
*
* @return {string} Parent page
*/
SourceHandler
.
prototype
.
getParentPage
=
function
()
{
return
this
.
parentPage
;
};
/**
* Set template source code parameters
*
* @param {string[]} params Parameters from the template source code
*/
SourceHandler
.
prototype
.
setTemplateSourceCodeParams
=
function
(
params
)
{
this
.
templateSourceCodeParams
=
params
;
};
/**
* Set template source code parameters
*
* @return {string[]} Parameters from the template source code
*/
SourceHandler
.
prototype
.
getTemplateSourceCodeParams
=
function
()
{
return
this
.
templateSourceCodeParams
;
};
module
.
exports
=
SourceHandler
;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, May 16, 16:57 (11 h, 29 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
a2/56/aee9971e20d86ec6b656bc06c048
Default Alt Text
SourceHandler.js (8 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment