モジュール:Flexbox

    提供:ManyoWiki

    このモジュールについての説明文ページを モジュール:Flexbox/doc に作成できます

    local p = {}
    local args = mw.getCurrentFrame():getParent().args
    
    function p.get_orient()
    	-- Android < 4.44, Firefox 27用の関数
    	if
    		(args["direction"] == "column") or
    		(args["direction"] == "column-reverse")
    	then
    		return "vertical"
    	end
    
    	return "horizontal"
    end
    
    local orient = p.get_orient()
    local is_webkit_prefix_needed =
    	orient == "vertical" or args["force-row-legacy"] == "1"
    
    function p.main()
    	local container = p.createContainer(false)
    
    	local content = args["content"] or args["1"]
    	container:wikitext(content)
    
    	return tostring(container)
    end
    
    function p.opening()
    	local openingTag = tostring(p.createContainer(true)):gsub("/>$", ">")
    	return openingTag
    end
    
    function p.closing()
    	return "</div>"
    end
    
    function p.createContainer(selfClosing)
    	local html_create_args = {}
    	if (selfClosing) then
    		html_create_args = { selfClosing = true }
    	end
    
    	local container = mw.html.create('div', html_create_args)
    
    	container:addClass("tpl-flexbox")
    	container = p.set_style_display(container)
    	container = p.set_style_direction(container)
    	container = p.set_style_flow(container)
    	container = p.set_style_justify_content(container)
    	container = p.set_style_align_items(container)
    	container = p.set_style_align_content(container)
    	container = p.set_style_gap(container)
    	container:cssText("-webkit-box-sizing: border-box") --Android 4.3用
    	container:cssText("-moz-box-sizing: border-box") --Firefox =< 28用
    	container:cssText("box-sizing: border-box")
    	container = p.set_style_others(container)
    
    	return container
    end
    
    function p.set_style_display(elm)
    	if is_webkit_prefix_needed then
    		-- Android < 4.44 は、この場合以外は display: block; のままとする。
    		elm:cssText("display: -webkit-box")
    	end
    	elm:cssText("display: -ms-flexbox; display: flex")
    	return elm;
    end
    
    function p.set_style_direction(elm)
    	-- Android < 4.44 と Firefox 27 のみの設定。他は flex-flow が優先される
    	if orient == "vertical" then
    		elm:cssText("-webkit-box-orient: vertical")
    
    		if args["direction"] == "column" then
    			elm:cssText("flex-direction: column")
    		else
    			elm:cssText("-webkit-box-direction: reverse")
    			elm:cssText("flex-direction: reverse")
    		end
    	else
    		if args["force-row-legacy"] == "1" then
    			elm:cssText("-webkit-box-orient: horizontal")
    
    			if args["direction"] == "row" then
    				elm:cssText("flex-direction: row")
    			else
    				elm:cssText("-webkit-box-direction: reverse")
    				elm:cssText("flex-direction: row-reverse")
    			end
    		else
    			-- 上記以外の場合は、Firefox 27の表示不具合を避けるために column とする。
    			elm:cssText("flex-direction: column")
    		end
    	end
    
    	return elm
    end
    
    function p.set_style_flow(elm)
    	local direction = args["direction"]
    	local wrap = args["wrap"]
    
    	if not(
    		direction == "column" or direction == "column-reverse" or
    		direction == "row-reverse"
    	)  then
    		direction = "row"
    	end
    
    	if not(wrap == "wrap-reverse" or wrap == "nowrap") then
    		wrap = "wrap"
    	end
    
    	elm:cssText("-ms-flex-flow: " .. direction .. " " .. wrap .. "") --IE10用
    	elm:cssText("flex-flow: " .. direction .. " " .. wrap .. "")
    
    	return elm
    end
    
    function p.set_style_justify_content(elm)
    	local justify_content = args["justify-content"]
    
    	if p.contains({
    		"flex-start", "flex-end", "start", "end", "center",
    		"space-between", "space-around", "space-evenly"
    	}, justify_content) then
    
    		local webkit_ms_value --IE10, Android4.3用
    		if string.find(justify_content, "space") then
    			webkit_ms_value = "justify"
    		else
    			webkit_ms_value = justify_content:gsub("flex-", "")
    		end
    
    		if is_webkit_prefix_needed then --Android 4.3用
    			elm:cssText("-webkit-box-align: " .. webkit_ms_value .. "")
    		end
    		elm:cssText("-ms-flex-align: ".. webkit_ms_value .. "") --IE10用
    		if p.contains({"start", "end"}, justify_content) then
    			-- IE11, Edge < 92, Firefox < 44, Chrome < 92, Opera, Android < 4.4.4用
    			elm:cssText("justify-content: flex-" .. justify_content .. "")
    		end
    		if justify_content == "space-evenly" then
    			-- IE11, Edge < 18, Firefox < 51, Chrome < 59, Safari < 10.1, Opera < 46,
    			-- Android < 4.4.4用
    			elm:cssText("justify-content: space-around")
    		end
    		elm:cssText("justify-content: " .. justify_content .. "")
    	end
    
    	return elm
    end
    
    function p.set_style_align_items(elm)
    	local align_items = args["align-items"]
    
    	if p.contains({
    		"stretch", "flex-start", "flex-end", "start", "end", "center", "baseline"
    	}, align_items) then
    		local webkit_ms_value = align_items:gsub("flex-", "")
    		if is_webkit_prefix_needed then --Android 4.3用
    			elm:cssText("-webkit-box-align: " .. webkit_ms_value .. "")
    		end
    
    		elm:cssText("-ms-flex-align: " .. webkit_ms_value .. "") --IE10用
    		if p.contains({"start", "end"}, align_items) then
    			-- IE11, Edge < 92, Firefox < 44, Chrome < 92, Safari, Opera < 43,
    			-- Android < 4.4.4用
    			elm:cssText("align-items: flex-" .. align_items .. "")
    		end
    		elm:cssText("align-items: " .. align_items .. "")
    	end
    
    	return elm
    end
    
    function p.set_style_align_content(elm)
    	local align_content = args["align-content"]
    
    	if p.contains({
    		"stretch", "flex-start", "flex-end", "start", "end", "center",
    		"space-between", "space-around", "space-evenly"
    	}, align_content) then
    		local ms_value --IE10用
    		if align_content == "space-between" then
    			ms_value = "justify"
    		elseif align_content == "space-around" then
    			ms_value = "distribute"
    		else
    			ms_value= align_content:gsub("flex-", "")
    		end
    		elm:cssText("-ms-flex-line-pack: " .. ms_value .. "")
    
    		if p.contains({"start", "end"}, align_content) then
    			-- IE11, Edge < 92, Firefox < 44, Chrome < 92, Safari, Opera,
    			-- Android < 4.4.4用
    			elm:cssText("align-content: flex-" .. align_content .. "")
    		end
    		if align_content == "space-evenly" then
    			-- IE11, Edge < 18, Firefox < 51, Chrome < 59, Safari < 10.1, Opera < 46,
    			-- Android < 4.4.4用
    			elm:cssText("align-content: space-around")
    		end
    		elm:cssText("align-content: " .. align_content .. "")
    	end
    
    	return elm
    end
    
    function p.set_style_gap(elm)
    	local gap = args["gap"]
    	elm:cssText("gap: " .. (args["gap"] or "0 1em") .. "")
    	return elm
    end
    
    function p.set_style_others(elm)
    	local style = args["style"]
    	if style then
    		style = style:gsub("\"", "")
    		elm:cssText(style)
    	end
    	return elm
    end
    
    function p.contains(list, str)
    	for i, elm in pairs(list) do
    		if elm == str then
    			return true
    		end
    	end
    	return false
    end
    
    return p