From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.

//<nowiki>



/**

 * –––––

 *       YOU ARE FULLY RESPONSIBLE FOR PUBLISHING EDITS USING THIS SCRIPT

 * –––––

 *

 * This script is not ready for use, unless of course, if you know what you are doing.

 * You must verify if the conversion is successful and modify if not.

 * Recommended to also use the [[User:Trappist the monk/HarvErrors]] script in conjunction.

 */



$.when(

    $.ready

).then(function () {

    // Only on main namespace or sandbox

    if ( ! 0, 2].includes(mw.config.get('wgNamespaceNumber'))) {

        return

    }



    let articleName = mw.config.get('wgPageName')

	articleName = encodeURIComponent(articleName); // fix bug involving & not getting converted to &amp;

	let pageIsSandbox = articleName.match(/sandbox$/)



    // Only in sandbox in user namespace

    if (2 === mw.config.get('wgNamespaceNumber') && ! pageIsSandbox) {

        return

    }



    let notifyTitle = 'Books-to-Sfn'



    // Activate portlet when VE source editor is enabled

    mw.hook( 've.activationComplete' ).add(function () {

        // Remove portlet when VE visual editor is enabled

        if (0 === $('.ve-ui-surface-source').length) {

            $('#ds-books-to-sfn').remove()



            return

        }



        $.when(

            mw.loader.using(  'mediawiki.util'  )

        ).then( function () {

            main()

        })

    })



    // Remove portlet when VE is deactivated

    mw.hook( 've.deactivationComplete' ).add(function () {

        $('#ds-books-to-sfn').remove()

    })



    function main() {

        const node = mw.util.addPortletLink('p-tb', '#', 'Books to Sfn', 'ds-books-to-sfn', 'Convert {{cite book}} to {{Sfn}}')



        $( node ).click(function (e) {

            let books = []

            let textBox = $('#wpTextbox1')

            let match, page, cite

            let errors = 0

            let index = 0

            let errorMatches = []



            if ( ! checkIfRefSectionExists(textBox)) {

                return

            }



            // ToDo Add support for quotes?



            while (true) {

                match = getNextMatch(index)



                if (null === match) {

                    break

                }



                // Determine author names

                let authorNames = determineAuthorNames(match2], 'last')

                console.log('Last name(s)', authorNames)



                if (0 === authorNames.length) {

                    authorNames = determineAuthorNames(match2], 'author')

                    console.log('Author(s)', authorNames)

                }



                if (0 === authorNames.length) {

                    authorNames = determineAuthorNames(match2], 'editor')

                    console.log('Editor(s)', authorNames)

                }



                if (authorNames.length > 4) {

                    console.error('More than four authors found. Please fix it manually.', authorNames, match)

                    // mw.notify('More than four authors found. Please fix it manually.', {

                    //     type: 'error',

                    //     title: notifyTitle,

                    // })

                    errors++

                    errorMatches.push({

                        error: 'More than four authors found',

                        match,

                    })



                    // Increment index as we need the next match

                    index = match.index + 1



                    break

                }



                if (0 === authorNames.length) {

                    console.error('Last name(s) / author(s) / editor(s) could not be determined. Please fix it manually.', authorNames, match)

                    // mw.notify('Last name(s) and author(s) could not be determined. Please fix it manually.', {

                    //     type: 'error',

                    //     title: notifyTitle,

                    // })

                    errors++

                    errorMatches.push({

                        error: 'Last name(s) / author(s) / editor(s) could not be determined',

                        match,

                    })



                    // Increment index as we need the next match

                    index = match.index + 1



                    continue

                }

                // End author names



                // Determine year

                let year = determineYear(match2])

                console.log('Year', year)



                if (null === year) {

                    console.error('Year could not be determined. Please fix it manually.', match)

                    // mw.notify('Year could not be determined. Please fix it manually.', {

                    //     type: 'error',

                    //     title: notifyTitle,

                    // })

                    errors++

                    errorMatches.push({

                        error: 'Year could not be determined',

                        match,

                    })



                    // Increment index as we need the next match

                    index = match.index + 1



                    break

                }



                // Determine page

                ({page, cite} = determinePage(match2]))

                console.log('Page(s)', page)

                console.log(cite)



                // Duplicate Refs to replace with Sfn

                duplicateRefs(textBox, match1], match0])



                // Replace with Sfn

                replaceWithSfn(textBox, authorNames, year, page, match0])



                books.push(cite)



                // One conversion per click

                break

            }



            if (0 === books.length) {

                if (errors > 0) {

                    mw.notify(`First error: ${errorMatches0]['error'}. Please fix it manually.`, {

                        type: 'error',

                        title: `${notifyTitle}: ${errors} error(s)`,

                        autoHideSeconds: 'long',

                    })



                    // Highlight the first error

                    let content = textBox.textSelection('getContents')



                    textBox.textSelection('setSelection', {

                        start: content.indexOf(errorMatches0]['match'][0]),

                        end: content.indexOf(errorMatches0]['match'][0]) + errorMatches0]['match'][0].length,

                    })



                    console.log(errorMatches)

                } else {

                    mw.notify('No books to convert', {

                        title: notifyTitle,

                    })

                }



                return

            }



            // Create Bibliography sub-section under References

            createBiblioSectionIfNotExists(textBox)



            // Add Sfns to Bibliography section

            addBooksToBibliography(textBox, books)



            // Hook to add edit summary

            mw.hook( 've.saveDialog.stateChanged' ).add(prefillEditSummary)



            e.preventDefault()

        })

    }



    const matchRe = /<ref(?: name=["']?(:?[\w\s]+)["']?)?> *(\{\{cite book\s?\|[|\w\s=?-–-—&'#.:+,%\/[\]()]+\}\})<\/ref>/imu

    const yearRe = /(?<=year\s*=)([\w\s]*)(?=\||}})/im

    const dateRe = /(?<!access-?)date\s*=([\w\s-]*)(?=\||}})/im

    const pageRe = /\|\s*page\s*=([\w\s]*)(?=\||}})/im

    const pagesRe = /\|\s*pages\s*=([\w\s–]*)(?=\||}})/im

    const reflistRe = /==\s?References\s?==\s*{{Reflist(\|.*)?}}/im

    const biblioRe = /(===? ?Bibliography ?===?\s?\{\{Refbegin(\|.*)?\}\}\s(?:\*\s\{\{cite book[|\w\s=?-–-&'#.:+,%\/[\]()]+\}\}\s){0,})\{\{Refend\}\}/imu



    function getNextMatch(index) {

        console.log('Index for match to start from', index)

        const content = $('#wpTextbox1').textSelection('getContents')



        if ( ! matchRe.test(content.substring(index))) {

            console.log('No matches')



            return null

        }



        return matchRe.exec(content.substring(index))

    }



    function determineAuthorNames(cite, type) {

        let match

        let names = []

        let nameReStr = `\\|\\s*${type}\\s*=([\\w\\s\\.]*)(?=\\|\|\\}\\})`

        let re = new RegExp(nameReStr, 'imu')



        console.log(cite)



        // Determine name without index

        if (re.test(cite)) {

            match = re.exec(cite)

            names.push(match1].trim())

        }



        let nameIndex = 1



        // Determine nth name with indexing

        while (true) {

            nameReStr = `\\|\\s*${type}${nameIndex}\\s*=([\\w\\s\\.]*)(?=\\|\|\\}\\})`

            re = new RegExp(nameReStr, 'imu')



            // nth name not found. No further searches for names

            if ( ! re.test(cite)) {

                break

            }



            match = re.exec(cite)

            names.push(match1].trim())



            nameIndex++

        }



        return names

    }



    function determineYear(cite) {

        if (yearRe.test(cite)) {

            return yearRe.exec(cite)[1].trim()

        }



        // Determine year from date

        if ( ! dateRe.test(cite)) {

            return null

        }



        return (new Date(dateRe.exec(cite)[1])).getFullYear()

    }



    function determinePage(cite) {

        let result = {

            page: '',

            cite,

        }



        if (pageRe.test(cite)) {

            result.page = `|p=${pageRe.exec(cite)[1].trim()}`

            result.cite = cite.replace(pageRe, '')

        } else {

            if (pagesRe.test(cite)) {

                result.page = `|pp=${pagesRe.exec(cite)[1].trim()}`

                result.cite = cite.replace(pagesRe, '')

            }

        }



        return result

    }



    // Duplicate Refs to replace with Sfn

    function duplicateRefs(textBox, refName, fullRef) {

        console.log('RefName', refName)



        // Ref not duplicated

        if (undefined === refName) {

            return

        }



        const reStr = `<ref name=\["']?${refName}\["']? ?\\/>`

        const content = textBox.textSelection('getContents')



        textBox.textSelection('setContents', content.replaceAll(new RegExp(reStr, 'imgu'), fullRef))

    }



    function replaceWithSfn(textBox, authorNames, year, page, fullRef) {

        // page will have pipe set

        let sfn = `{{Sfn|${authorNames.join('|')}|${year}${page}}}`



        console.log('Sfn', sfn);



        const content = textBox.textSelection('getContents')



        textBox.textSelection('setContents', content.replaceAll(fullRef, sfn))



        mw.notify( `Replaced ${sfn}`, {

            type: 'success',

            title: notifyTitle,

        })

    }



    function checkIfRefSectionExists(textBox) {

        const content = textBox.textSelection('getContents')



        // Bibliography section exists

        if (biblioRe.test(content)) {

            return true

        }



        // References section exists, but not Bibliography which can be created

        if (reflistRe.test(content)) {

            return true;

        }



        // References section regex failure

        mw.notify('References section not found. Possible regex failure.', {

            type: 'error',

            title: notifyTitle,

        })



        return false

    }



    function createBiblioSectionIfNotExists(textBox) {

        const content = textBox.textSelection('getContents')



        // Section exists

        if (biblioRe.test(content)) {

            return;

        }



        const reflistMatch = reflistRe.exec(content)



        // Add Bibliography section

        textBox.textSelection('encapsulateSelection', {

            post: `\n\n=== Bibliography ===\n{{Refbegin}}\n{{Refend}}`,

            selectionStart: content.indexOf(reflistMatch0]),

            selectionEnd: content.indexOf(reflistMatch0]) + reflistMatch0].length,

        })

    }



    function addBooksToBibliography(textBox, books) {

        const content = textBox.textSelection('getContents')



        let bookRefStr = ''

        for (let book of books) {

            bookRefStr += `* ${book}\n`

        }



        const biblioMatch = biblioRe.exec(content)



        textBox.textSelection('encapsulateSelection', {

            post: bookRefStr,

            selectionStart: content.indexOf(biblioMatch1]),

            selectionEnd: content.indexOf(biblioMatch1]) + biblioMatch1].length,

        })

    }



    function prefillEditSummary() {

        if (ve.init.target.saveDialog) {

            ve.init.target.saveDialog.editSummaryInput.$input.val('Convert [[Template:Cite book|{{cite book}}]] reference(s) to [[Template:Sfn|Sfn]]s ([[User:DaxServer/BooksToSfn|BooksToSfn.js]])')

        }



        // Remove hook upon prefilling

        mw.hook( 've.saveDialog.stateChanged' ).remove(prefillEditSummary)

    }

})



//</nowiki>
From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.

//<nowiki>



/**

 * –––––

 *       YOU ARE FULLY RESPONSIBLE FOR PUBLISHING EDITS USING THIS SCRIPT

 * –––––

 *

 * This script is not ready for use, unless of course, if you know what you are doing.

 * You must verify if the conversion is successful and modify if not.

 * Recommended to also use the [[User:Trappist the monk/HarvErrors]] script in conjunction.

 */



$.when(

    $.ready

).then(function () {

    // Only on main namespace or sandbox

    if ( ! 0, 2].includes(mw.config.get('wgNamespaceNumber'))) {

        return

    }



    let articleName = mw.config.get('wgPageName')

	articleName = encodeURIComponent(articleName); // fix bug involving & not getting converted to &amp;

	let pageIsSandbox = articleName.match(/sandbox$/)



    // Only in sandbox in user namespace

    if (2 === mw.config.get('wgNamespaceNumber') && ! pageIsSandbox) {

        return

    }



    let notifyTitle = 'Books-to-Sfn'



    // Activate portlet when VE source editor is enabled

    mw.hook( 've.activationComplete' ).add(function () {

        // Remove portlet when VE visual editor is enabled

        if (0 === $('.ve-ui-surface-source').length) {

            $('#ds-books-to-sfn').remove()



            return

        }



        $.when(

            mw.loader.using(  'mediawiki.util'  )

        ).then( function () {

            main()

        })

    })



    // Remove portlet when VE is deactivated

    mw.hook( 've.deactivationComplete' ).add(function () {

        $('#ds-books-to-sfn').remove()

    })



    function main() {

        const node = mw.util.addPortletLink('p-tb', '#', 'Books to Sfn', 'ds-books-to-sfn', 'Convert {{cite book}} to {{Sfn}}')



        $( node ).click(function (e) {

            let books = []

            let textBox = $('#wpTextbox1')

            let match, page, cite

            let errors = 0

            let index = 0

            let errorMatches = []



            if ( ! checkIfRefSectionExists(textBox)) {

                return

            }



            // ToDo Add support for quotes?



            while (true) {

                match = getNextMatch(index)



                if (null === match) {

                    break

                }



                // Determine author names

                let authorNames = determineAuthorNames(match2], 'last')

                console.log('Last name(s)', authorNames)



                if (0 === authorNames.length) {

                    authorNames = determineAuthorNames(match2], 'author')

                    console.log('Author(s)', authorNames)

                }



                if (0 === authorNames.length) {

                    authorNames = determineAuthorNames(match2], 'editor')

                    console.log('Editor(s)', authorNames)

                }



                if (authorNames.length > 4) {

                    console.error('More than four authors found. Please fix it manually.', authorNames, match)

                    // mw.notify('More than four authors found. Please fix it manually.', {

                    //     type: 'error',

                    //     title: notifyTitle,

                    // })

                    errors++

                    errorMatches.push({

                        error: 'More than four authors found',

                        match,

                    })



                    // Increment index as we need the next match

                    index = match.index + 1



                    break

                }



                if (0 === authorNames.length) {

                    console.error('Last name(s) / author(s) / editor(s) could not be determined. Please fix it manually.', authorNames, match)

                    // mw.notify('Last name(s) and author(s) could not be determined. Please fix it manually.', {

                    //     type: 'error',

                    //     title: notifyTitle,

                    // })

                    errors++

                    errorMatches.push({

                        error: 'Last name(s) / author(s) / editor(s) could not be determined',

                        match,

                    })



                    // Increment index as we need the next match

                    index = match.index + 1



                    continue

                }

                // End author names



                // Determine year

                let year = determineYear(match2])

                console.log('Year', year)



                if (null === year) {

                    console.error('Year could not be determined. Please fix it manually.', match)

                    // mw.notify('Year could not be determined. Please fix it manually.', {

                    //     type: 'error',

                    //     title: notifyTitle,

                    // })

                    errors++

                    errorMatches.push({

                        error: 'Year could not be determined',

                        match,

                    })



                    // Increment index as we need the next match

                    index = match.index + 1



                    break

                }



                // Determine page

                ({page, cite} = determinePage(match2]))

                console.log('Page(s)', page)

                console.log(cite)



                // Duplicate Refs to replace with Sfn

                duplicateRefs(textBox, match1], match0])



                // Replace with Sfn

                replaceWithSfn(textBox, authorNames, year, page, match0])



                books.push(cite)



                // One conversion per click

                break

            }



            if (0 === books.length) {

                if (errors > 0) {

                    mw.notify(`First error: ${errorMatches0]['error'}. Please fix it manually.`, {

                        type: 'error',

                        title: `${notifyTitle}: ${errors} error(s)`,

                        autoHideSeconds: 'long',

                    })



                    // Highlight the first error

                    let content = textBox.textSelection('getContents')



                    textBox.textSelection('setSelection', {

                        start: content.indexOf(errorMatches0]['match'][0]),

                        end: content.indexOf(errorMatches0]['match'][0]) + errorMatches0]['match'][0].length,

                    })



                    console.log(errorMatches)

                } else {

                    mw.notify('No books to convert', {

                        title: notifyTitle,

                    })

                }



                return

            }



            // Create Bibliography sub-section under References

            createBiblioSectionIfNotExists(textBox)



            // Add Sfns to Bibliography section

            addBooksToBibliography(textBox, books)



            // Hook to add edit summary

            mw.hook( 've.saveDialog.stateChanged' ).add(prefillEditSummary)



            e.preventDefault()

        })

    }



    const matchRe = /<ref(?: name=["']?(:?[\w\s]+)["']?)?> *(\{\{cite book\s?\|[|\w\s=?-–-—&'#.:+,%\/[\]()]+\}\})<\/ref>/imu

    const yearRe = /(?<=year\s*=)([\w\s]*)(?=\||}})/im

    const dateRe = /(?<!access-?)date\s*=([\w\s-]*)(?=\||}})/im

    const pageRe = /\|\s*page\s*=([\w\s]*)(?=\||}})/im

    const pagesRe = /\|\s*pages\s*=([\w\s–]*)(?=\||}})/im

    const reflistRe = /==\s?References\s?==\s*{{Reflist(\|.*)?}}/im

    const biblioRe = /(===? ?Bibliography ?===?\s?\{\{Refbegin(\|.*)?\}\}\s(?:\*\s\{\{cite book[|\w\s=?-–-&'#.:+,%\/[\]()]+\}\}\s){0,})\{\{Refend\}\}/imu



    function getNextMatch(index) {

        console.log('Index for match to start from', index)

        const content = $('#wpTextbox1').textSelection('getContents')



        if ( ! matchRe.test(content.substring(index))) {

            console.log('No matches')



            return null

        }



        return matchRe.exec(content.substring(index))

    }



    function determineAuthorNames(cite, type) {

        let match

        let names = []

        let nameReStr = `\\|\\s*${type}\\s*=([\\w\\s\\.]*)(?=\\|\|\\}\\})`

        let re = new RegExp(nameReStr, 'imu')



        console.log(cite)



        // Determine name without index

        if (re.test(cite)) {

            match = re.exec(cite)

            names.push(match1].trim())

        }



        let nameIndex = 1



        // Determine nth name with indexing

        while (true) {

            nameReStr = `\\|\\s*${type}${nameIndex}\\s*=([\\w\\s\\.]*)(?=\\|\|\\}\\})`

            re = new RegExp(nameReStr, 'imu')



            // nth name not found. No further searches for names

            if ( ! re.test(cite)) {

                break

            }



            match = re.exec(cite)

            names.push(match1].trim())



            nameIndex++

        }



        return names

    }



    function determineYear(cite) {

        if (yearRe.test(cite)) {

            return yearRe.exec(cite)[1].trim()

        }



        // Determine year from date

        if ( ! dateRe.test(cite)) {

            return null

        }



        return (new Date(dateRe.exec(cite)[1])).getFullYear()

    }



    function determinePage(cite) {

        let result = {

            page: '',

            cite,

        }



        if (pageRe.test(cite)) {

            result.page = `|p=${pageRe.exec(cite)[1].trim()}`

            result.cite = cite.replace(pageRe, '')

        } else {

            if (pagesRe.test(cite)) {

                result.page = `|pp=${pagesRe.exec(cite)[1].trim()}`

                result.cite = cite.replace(pagesRe, '')

            }

        }



        return result

    }



    // Duplicate Refs to replace with Sfn

    function duplicateRefs(textBox, refName, fullRef) {

        console.log('RefName', refName)



        // Ref not duplicated

        if (undefined === refName) {

            return

        }



        const reStr = `<ref name=\["']?${refName}\["']? ?\\/>`

        const content = textBox.textSelection('getContents')



        textBox.textSelection('setContents', content.replaceAll(new RegExp(reStr, 'imgu'), fullRef))

    }



    function replaceWithSfn(textBox, authorNames, year, page, fullRef) {

        // page will have pipe set

        let sfn = `{{Sfn|${authorNames.join('|')}|${year}${page}}}`



        console.log('Sfn', sfn);



        const content = textBox.textSelection('getContents')



        textBox.textSelection('setContents', content.replaceAll(fullRef, sfn))



        mw.notify( `Replaced ${sfn}`, {

            type: 'success',

            title: notifyTitle,

        })

    }



    function checkIfRefSectionExists(textBox) {

        const content = textBox.textSelection('getContents')



        // Bibliography section exists

        if (biblioRe.test(content)) {

            return true

        }



        // References section exists, but not Bibliography which can be created

        if (reflistRe.test(content)) {

            return true;

        }



        // References section regex failure

        mw.notify('References section not found. Possible regex failure.', {

            type: 'error',

            title: notifyTitle,

        })



        return false

    }



    function createBiblioSectionIfNotExists(textBox) {

        const content = textBox.textSelection('getContents')



        // Section exists

        if (biblioRe.test(content)) {

            return;

        }



        const reflistMatch = reflistRe.exec(content)



        // Add Bibliography section

        textBox.textSelection('encapsulateSelection', {

            post: `\n\n=== Bibliography ===\n{{Refbegin}}\n{{Refend}}`,

            selectionStart: content.indexOf(reflistMatch0]),

            selectionEnd: content.indexOf(reflistMatch0]) + reflistMatch0].length,

        })

    }



    function addBooksToBibliography(textBox, books) {

        const content = textBox.textSelection('getContents')



        let bookRefStr = ''

        for (let book of books) {

            bookRefStr += `* ${book}\n`

        }



        const biblioMatch = biblioRe.exec(content)



        textBox.textSelection('encapsulateSelection', {

            post: bookRefStr,

            selectionStart: content.indexOf(biblioMatch1]),

            selectionEnd: content.indexOf(biblioMatch1]) + biblioMatch1].length,

        })

    }



    function prefillEditSummary() {

        if (ve.init.target.saveDialog) {

            ve.init.target.saveDialog.editSummaryInput.$input.val('Convert [[Template:Cite book|{{cite book}}]] reference(s) to [[Template:Sfn|Sfn]]s ([[User:DaxServer/BooksToSfn|BooksToSfn.js]])')

        }



        // Remove hook upon prefilling

        mw.hook( 've.saveDialog.stateChanged' ).remove(prefillEditSummary)

    }

})



//</nowiki>

Videos

Youtube | Vimeo | Bing

Websites

Google | Yahoo | Bing

Encyclopedia

Google | Yahoo | Bing

Facebook