SQLの窓

2018年04月14日


Python 3.6 で GET/POST メソッドを想定した CGI 用の簡易テンプレートを作成してみました

Eclipse で実行させるのと、WWWサーバー( ここでは AN HTTP Server )で実行させるのとでは、やはりもっといろいろな切り口の理解が必要になります。

とにかく、CGI としてベタな QUERY_STRING を使用してベタな format で作成後、f-stringヒアドキュメントで HTML 部分を簡潔にして、最後に cgi モジュールで GETとPOST を兼用にしました。(FieldStorage() の戻りの内容が変更できないようなので、単純な dict に入れ替えています。)

▼ GET/POST 共用 : 結局 cgi モジュール で作成 : f-string ヒアドキュメント埋め込み
import cgi
import cgitb
cgitb.enable()

import sys
import io
import os
import urllib.parse

sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')

print("Content-Type: text/html; charset=utf-8")
print( "Expires: Thu, 19 Nov 1981 08:52:00 GMT" )
print( "Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0" )
print( "Pragma: no-cache" )
print()

form = cgi.FieldStorage()

fields = {}
fld_names = {"氏名": "field1", "フリガナ":"field2"}
for value in fld_names.values():
	if value not in form:
		fields[value] = ""
	else:
		fields[value] = form[value].value

out_client = f"""<!DOCTYPE html>
<html>
<head>
</head>
<body>
	<form method="post">
		<p>氏名 : <input type="text" name="{fld_names["氏名"]}" value="{fields[fld_names["氏名"]]}"></p>
		<p>フリガナ : <input type="text" name="{fld_names["フリガナ"]}" value="{fields[fld_names["フリガナ"]]}"></p>
		<p>送信 : <input type="submit" name="send" value="送信"></p>
	</form>
</body>
</html>"""

print(out_client)

▼ GET のみ f-string を使った、ヒアドキュメント埋め込み
import cgitb
cgitb.enable()

import sys
import io
import os
import urllib.parse

sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')

print("Content-Type: text/html; charset=utf-8")
print( "Expires: Thu, 19 Nov 1981 08:52:00 GMT" )
print( "Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0" )
print( "Pragma: no-cache" )
print()

try:
	qs = os.environ["QUERY_STRING"]
except KeyError as e:
	qs = ""

get =  urllib.parse.parse_qs(qs)

fld_names = {"氏名": "field1", "フリガナ":"field2"}
for value in fld_names.values():
	if get.get(value) is None:
		get[value] = [""]

out_client = f"""<!DOCTYPE html>
<html>
<head>
</head>
<body>
	<form>
		<p>氏名 : <input type="text" name="{fld_names["氏名"]}" value="{get.get(fld_names["氏名"])[0]}"></p>
		<p>フリガナ : <input type="text" name="{fld_names["フリガナ"]}" value="{get.get(fld_names["フリガナ"])[0]}"></p>
		<p>送信 : <input type="submit" name="send" value="送信"></p>
	</form>
</body>
</html>"""

print(out_client)

▼ GET のみ : format を使った、クォートの作成が面倒な埋め込み
import cgitb
cgitb.enable()

import sys
import io
import os
import urllib.parse

sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')

print("Content-Type: text/html; charset=utf-8")
print( "Expires: Thu, 19 Nov 1981 08:52:00 GMT" )
print( "Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0" )
print( "Pragma: no-cache" )
print()

try:
	qs = os.environ["QUERY_STRING"]
except KeyError as e:
	qs = ""

get =  urllib.parse.parse_qs(qs)

fld_names = {"氏名": "field1", "フリガナ":"field2"}
for value in fld_names.values():
	if get.get(value) is None:
		get[value] = [""]

out_client = """<!DOCTYPE html>
<html>
<head>
</head>
<body>
	<form>
		<p>氏名 : <input type="text" name=\"""" + fld_names["氏名"] + """\" value="{""" + fld_names["氏名"] + """}"></p>
		<p>フリガナ : <input type="text" name=\"""" + fld_names["フリガナ"] + """\" value="{""" + fld_names["フリガナ"] + """}"></p>
		<p>送信 : <input type="submit" name="send" value="送信"></p>
	</form>
</body>
</html>"""

out_client = out_client.format(
	field1=get.get(fld_names["氏名"])[0],
	field2=get.get(fld_names["フリガナ"])[0]
)

print(out_client)

AN HTTP Server の設定



テストにはまだまだ使える(重宝する) AN HTTP Server の正しい使用方法



タグ:Python CGI
posted by lightbox at 2018-04-14 21:19 | Python | このブログの読者になる | 更新情報をチェックする

WordPress の投稿画面のカスタマイズ3つ / フォント・記事リンク・一覧のリンク

PHP を解っていても、WordPress のカスタマイズとなると、インターネットに頼るしかありません。

投稿のテキストエリアのフォントを変更

まず最初に投稿のテキストエリアのフォントを変更したかったのですが、最初見つけた『editor-style.css』を使う方法はうまくいかなかったので、もっとダイレクトに function.php 内で行う方法を見つけました。

WordPress投稿画面 テキストエディタのフォントを変更したい

しかし、ここのコードは HTML の出力を echo で行っていたのでカスタマイズには不向きです。最初 PHP タグを閉じてやろうかと思いましたが、それだと失敗した場合影響が大きくて一般には不向きなのでヒアドキュメントで実装しました。
function change_editor_font(){

print <<<STYLE
<style>
textarea#content.wp-editor-area {
	font-family: "ヒラギノ角ゴPro W3","Hiragino Kaku Gothic Pro","メイリオ",Meiryo,"MS Pゴシック",Verdana,Arial,Helvetica,sans-serif;
	font-size: 16px;
	color: #000000;
}
</style>

STYLE;
}
add_action('admin_head', 'change_editor_font');


投稿時の記事リンクをクリックした場合新しいしいタブを開く

これは、『投稿画面のパーマリンク編集部分とクイック編集を非表示にする方法』という記事内にあったコードを転用しました。

※ デベロッパーツールで見ると、id="sample-permalink" となってるリンクです。
add_filter( 'get_sample_permalink_html', 'hide_permalinkedit' );
function hide_permalinkedit( $permalink_html ) {
  $permalink_html = preg_replace( "/<a /" , "<a target=\"_blank\" " , $permalink_html );
  return $permalink_html;
}


投稿一覧の記事リンクをクリックした場合も新しいしいタブを開く

▼ このリンクです


さすがに、function.php 経由ではできそうにも無かったので直接変更しました。アップデートで元に戻ると思いますが、まあそのたびに変えればいいので。

みつけるのに、まずデベロッパーツールで見たら、 rel= があったのでローカルに 『wp-admin/includes』をダウンロードして JGREP というフリーソフトで検索しました。

※ JGREP 2.0.5 はWin7 でも動作する、テキスト内文字列検索のできる結構人気の高いフリーソフトです





これで、class-wp-posts-list-table.php の中の該当部分を変更しました。
		if ( is_post_type_viewable( $post_type_object ) ) {
			if ( in_array( $post->post_status, array( 'pending', 'draft', 'future' ) ) ) {
				if ( $can_edit_post ) {
					$preview_link = get_preview_post_link( $post );
					$actions['view'] = sprintf(
						'<a href="%s" rel="bookmark" aria-label="%s">%s</a>',
						esc_url( $preview_link ),
						/* translators: %s: post title */
						esc_attr( sprintf( __( 'Preview &#8220;%s&#8221;' ), $title ) ),
						__( 'Preview' )
					);
				}
			} elseif ( 'trash' != $post->post_status ) {
				$actions['view'] = sprintf(
					'<a target="_blank" href="%s" rel="bookmark" aria-label="%s">%s</a>',
					get_permalink( $post->ID ),
					/* translators: %s: post title */
					esc_attr( sprintf( __( 'View &#8220;%s&#8221;' ), $title ) ),
					__( 'View' )
				);
			}
		}





タグ:WordPress
posted by lightbox at 2018-04-14 13:25 | WordPress | このブログの読者になる | 更新情報をチェックする

2018年04月10日


PowerShell : COM 経由(New-Object) + MySQL Connector/ODBC でループ処理をしながら更新

PowerShell をコマンドプロンプトからセキュリティの制限を回避して実行できるように以下のバッチファイルを Windows フォルダに置いています。

▼ ps.bat
@powershell -NoProfile -ExecutionPolicy Unrestricted "./%1.ps1"
これによって、カレントフォルダの .ps1 スクリプトファイルを名前を指定して実行できます。 ado_com_mysql.ps1 データベースから条件に合ったレコードを読みだして、CSV 形式で出力する為のテキストを作成して最後に出力します。 その処理中にレコード毎に更新を行っています。 CSV 形式のカンマは、常に項目の後ろに追加して、行が完成した後一文字を行の最後から削除して作成しています。( いわゆる Chop です ) ここでは、その為に $line.Substring(0,$line.Length-1) を実行しています。 Hey, Scripting Guy! Blog では、正規表現による置換を使った方法も紹介されています。 $error[0] | Format-List * -force は、$error の中のプロパティと内容を全て表示する方法です。 ▼ 参考 How to list all properties of a Powershell object? 実行はコマンドプロンプトから ps ado_com_mysql となります
$cn = New-Object -ComObject ADODB.Connection
$rs = New-Object -ComObject ADODB.Recordset

$driver = "{MySQL ODBC 5.3 Unicode Driver}"
$server = "localhost"
$db = "lightbox"
$user = "root"
$pass = ""

$connectionString = "Provider=MSDASQL;Driver={0};Server={1};DATABASE={2};UID={3};PWD={4};"
$connectionString = $connectionString -f $driver,$server,$db,$user,$pass

$connectionString


try {
	$cn.Open( $connectionString )
}
catch [Exception] {

	$error[0] | Format-List * -force
	exit

}

$rs.CursorType = 2
$rs.LockType = 3
$rs.Open( "select * from 社員マスタ where 社員コード <= '0004' ", $cn )

$text = ""
while( !$rs.EOF ) {

	$line = ""

	$line += "{0}{1}" -f $rs.Fields("社員コード").Value, ","
	$line += "{0}{1}" -f $rs.Fields("氏名").Value, ","
	$line += "{0}{1}" -f $rs.Fields("フリガナ").Value, ","
	$line += "{0}{1}" -f $rs.Fields("所属").Value, ","
	$line += "{0}{1}" -f $rs.Fields("性別").Value.ToString(), ","
	$line += "{0}{1}" -f $rs.Fields("給与").Value.ToString(), ","
	$line += "{0}{1}" -f $rs.Fields("手当").Value.ToString(), ","
	$line += "{0}{1}" -f $rs.Fields("管理者").Value, ","
	$line += "{0}{1}" -f $rs.Fields("作成日").Value.ToString("yyyy/MM/dd"), ","
	$line += "{0}{1}" -f $rs.Fields("更新日").Value.ToString("yyyy/MM/dd"), ","
	$line += "{0}{1}" -f $rs.Fields("生年月日").Value.ToString("yyyy/MM/dd"), ","

	$line = $line.Substring(0,$line.Length-1)

	$line += "`n"
	$text += $line

	$rs.Fields("管理者").Value = "0001"
	$rs.Update()

	$rs.MoveNext()
}

$text

if ( $cn.State -ge 1 ) {
	$cn.Close()
}



関連する記事

▼ Python + COM
Eclipse + Python(Pydev) : pywin32(COM使用の為) + MySQL Connector/ODBC でループ処理をしながら更新

▼ Ruby + COM
Eclipse + Ruby : win32ole(COM使用の為) + MySQL Connector/ODBC でループ処理をしながら更新



posted by lightbox at 2018-04-10 20:17 | PowerShell | このブログの読者になる | 更新情報をチェックする

Eclipse + Ruby : win32ole(COM使用の為) + MySQL Connector/ODBC でループ処理をしながら更新

前提条件

Eclipse は Pleiades Eclipse 4.7 Oxygen です。前提となる環境は以下を参照して下さい。

Pleiades Eclipse 4.7 Oxygen 2 Windows 64bit Ultimate Full Edition のインストールといろいろな準備
Pleiades Oxygen 2 の XAMPP 内の MySQL を利用可能にしてテストデータ(販売管理)を登録する

▼ プロジェクトの作成方法はこちらを参照して下さい
Pleiades Eclipse 4.7 Oxygen で Ruby を使って MySQL にアクセスする

Connector/ODBC 5.3.10

ADO から接続する場合、純粋に Windows からのアクセスになるので ODBC ドライバが必要になります。Ruby が 64ビットならば、ODBC ドライバも 64ビット用が必要になります。

ダウンロードページ

com_ado_mysql

以下は、ADO + COM で行われる標準的なレコードセットの読み込みと同時更新の処理です。
特徴的なのは、レコードセットの Fields コレクション( Field オブジェクト )を使用して値を直接セットして一行づつレコードを更新するところです。
require 'win32ole'

adOpenDynamic = 2
adLockOptimistic = 3

cn = WIN32OLE.new('ADODB.Connection')
rs = WIN32OLE.new('ADODB.Recordset')

driver = "{MySQL ODBC 5.3 Unicode Driver}"
server = "localhost"
db = "lightbox"
user = "root"
pass = ""

connectionString = "Provider=MSDASQL;Driver=%s;Server=%s;DATABASE=%s;UID=%s;PWD=%s;"
connectionString = format(connectionString, driver,server,db,user,pass)
puts connectionString

# **************************
# 接続
# **************************
begin
	cn.Open( connectionString )
rescue => ex
	print format("%d エラーが発生しました\n%s",ex.errno,ex.error)
	# 接続エラーの場合は終了
	exit!
end

rs.CursorType = adOpenDynamic
rs.LockType = adLockOptimistic
rs.Open( "select * from 社員マスタ where 社員コード <= '0004' ", cn )

while !rs.EOF do

	line = ""
	rs.Fields.each do |field|
		line << format(" %s |",field.Type)
	end
	line.chop!
	puts line

	line = ""
	rs.Fields.each do |field|
		if field.Type == 202 then
			line << format(" %s |",field.Value)
		end
		if field.Type == 3 then
			# nil 値あり
			line << format(" %s |",field.Value.to_s)
		end
		if field.Type == 135 then
			line << field.Value.strftime(" %Y/%m/%d |")
		end
	end
	line.chop!
	puts line

	print format("%s,",rs.Fields("社員コード").Value)
	print format("%s,",rs.Fields("氏名").Value)
	print format("%s,",rs.Fields("フリガナ").Value)
	print format("%s,",rs.Fields("所属").Value)
	print format("%d,",rs.Fields("性別").Value)
	print format("%d,",rs.Fields("給与").Value)
	if !rs.Fields("手当").Value.nil? then
		print format("%d,",rs.Fields("手当").Value)
	else
		print ","
	end
	print format("%s,",rs.Fields("管理者").Value)
	print rs.Fields("作成日").Value.strftime("%Y/%m/%d,")
	print rs.Fields("更新日").Value.strftime("%Y/%m/%d,")
	print rs.Fields("生年月日").Value.strftime("%Y/%m/%d\n")

	rs.Fields("管理者").Value = "0001"
	rs.Update()

	rs.MoveNext()

end

# **************************
# 接続解除
# **************************
if cn.State >= 1 then
	cn.Close()
end

print("終了しました\n")


CursorTypes, LockTypes, and CursorLocations

※ MySQL は 以下の三つの組み合わせのみ動作
adUseClient/adOpenStatic
adUseServer/adOpenForwardOnly
adUseServer/adOpenDynamic

※ ADO でデフォルトは adUseServer

エディタのタブの設定








タグ:ruby MySQL ODBC
posted by lightbox at 2018-04-10 19:46 | Ruby 2018 | このブログの読者になる | 更新情報をチェックする

PowerShell でエクスプローラでコピーしたファイルリストを取得して、テキストのクリップボードに再度コピーしなおす

Windows10 のデフォルトコマンドウインドウが、PowerShell になったので久しぶりに動作確認をしました。基本的に実行ポリシーは変わっておらず、そのままでは .ps1 スクリプトを実行できません。しかし、PowerShell のプロンプトから cmd と入力すれば従来のコマンドプロンプトになるので、以下のようにして実行します。

powershell -NoProfile -ExecutionPolicy Unrestricted .\test.ps1

▼ コマンドラインが長いので ps.bat を Windows フォルダに作成しておきます
@powershell -NoProfile -ExecutionPolicy Unrestricted "./%1.ps1"
※ カレントフォルダで ./ と 拡張子なしで実行できます。 ※ SHIFT キーを押しながらフォルダを右クリックで PowerShell ウインドウが開くので cmd と入力後使用します。 ファイルリストを \r\n 改行のテキストとしてクリップボードへ PowerShell では、.NET Framework を使用できるので、わざわざ C# 等で実行形式のアプリを作成せずとも、C# のコードを知っておればインターネットを調べながら成果物を作成するのはそれほど難しい事ではありません。 手軽に実行できる VBScript はまだ健在なので、VBScript から PowerShell のスクリプトを呼び出せば、かなりできる事の幅が膨らむのでは無いかと思っています。しかしいかんせん、PowerShell を真剣にやり出すとかなり面倒くさい事にもなりそうなので、しばらくは様子をうかがっていきたいと思っています。( csc.exe とか動かなくなってしまったので )
Add-Type -assemblyName System.Windows.Forms

$obj = [System.Windows.Forms.Clipboard]::GetFileDropList()

if ( $obj -eq $null ) {
	[System.Console]::WriteLine("NULL")
}
else {
	if ( $obj.Count -eq 0 ) {
		[System.Console]::WriteLine("データがありません")
	}
	else {
		$text = ""
		foreach($data in $obj){
			$text += $data + "`r`n"
		}
		[System.Windows.Forms.Clipboard]::SetText($text)
	}
}

ダウンロードした場合は、セキュリティの警告が出るので、エディタで上書き保存するかプロパティの『セキュリティ』で許可にチェックして『適用』します。

※ 参考 : PowerShellスクリプティングの第一歩
( 2007年09月20日 の記事なんですけど、いまさら Windows10 って大丈夫かなぁ... )



posted by lightbox at 2018-04-10 16:11 | PowerShell | このブログの読者になる | 更新情報をチェックする

2018年04月09日


Eclipse + Python(Pydev) : pywin32(COM使用の為) + MySQL Connector/ODBC でループ処理をしながら更新

前提条件

Eclipse は Pleiades Eclipse 4.7 Oxygen です。前提となる環境は以下を参照して下さい。

Pleiades Eclipse 4.7 Oxygen 2 Windows 64bit Ultimate Full Edition のインストールといろいろな準備
Pleiades Oxygen 2 の XAMPP 内の MySQL を利用可能にしてテストデータ(販売管理)を登録する

▼ プロジェクトの作成方法はこちらを参照して下さい
Pleiades Eclipse 4.7 Oxygen で Python を使って MySQL にアクセスする

pywin32 + COM

COM 経由で ADO を使って MySQL にアクセスする為に、pywin32 をインストールします。

インストールは、pip install pywin32 でインストールできます。但し、『Fatal error in launcher: Unable to create process using '"'』というエラーが出た場合は、以下のコマンドを実行してから再度実行して下さい。
python -m pip install -U pip
pywin32 の readme にもありますが、さらに『COMオブジェクトの登録やWindowsサービスの実装などの「システムワイド」機能でpywin32を使用する場合は』管理者権限のコマンドプロンプトから以下を実行します
python Scripts/pywin32_postinstall.py -install
▼ 実行結果
Copied pythoncom36.dll to C:\WINDOWS\system32\pythoncom36.dll
Copied pywintypes36.dll to C:\WINDOWS\system32\pywintypes36.dll
Registered: Python.Interpreter
Registered: Python.Dictionary
Registered: Python
-> Software\Python\PythonCore\3.6\Help[None]=None
-> Software\Python\PythonCore\3.6\Help\Pythonwin Reference[None]='C:\\pleiades\\python\\3\\Lib\\site-packages\\PyWin32.chm'
Pythonwin has been registered in context menu
Creating directory C:\pleiades\python\3\Lib\site-packages\win32com\gen_py
Shortcut for Pythonwin created
Shortcut to documentation created
The pywin32 extensions were successfully installed.
Connector/ODBC 5.3.10 ADO から接続する場合、純粋に Windows からのアクセスになるので ODBC ドライバが必要になります。Python が 64ビットならば、ODBC ドライバも 64ビット用が必要になります。 ダウンロードページ com_ado_mysql 以下は、ADO + COM で行われる標準的なレコードセットの読み込みと同時更新の処理です。 特徴的なのは、レコードセットの Fields コレクション( Field オブジェクト )を使用して値を直接セットして一行づつレコードを更新するところです。
import win32com.client

adOpenDynamic = 2
adLockOptimistic = 3

cn = win32com.client.Dispatch("ADODB.Connection")
rs = win32com.client.Dispatch("ADODB.Recordset")

driver = "{MySQL ODBC 5.3 Unicode Driver}"
server = "localhost"
DB = "lightbox"
User = "root"
Pass = ""

ConnectionString = "Provider=MSDASQL;Driver={0};Server={1};DATABASE={2};UID={3};PWD={4};"
ConnectionString = ConnectionString.format(driver,server,DB,User,Pass)
print(ConnectionString)

"""""""""""""""""""""""""""
接続
"""""""""""""""""""""""""""
try:
	cn.Open( ConnectionString )
except Exception as e:
	print( e )
	exit()

rs.CursorType = adOpenDynamic
rs.LockType = adLockOptimistic

rs.Open( "select * from 社員マスタ where 社員コード <= '0004' ", cn )

while not rs.EOF:

	print(rs.Fields("社員コード").Value,end=",")
	print(rs.Fields("氏名").Value, end=",")
	print(rs.Fields("フリガナ").Value, end=",")
	print(rs.Fields("所属").Value, end=",")
	print(rs.Fields("性別").Value, end=",")
	print(rs.Fields("給与").Value, end=",")
	print(rs.Fields("手当").Value, end=",")		# NULL の場合は None と出力
	print(rs.Fields("管理者").Value, end=",")
	print("{0:%Y/%m/%d}".format(rs.Fields("作成日").Value), end=",")
	print("{0:%Y/%m/%d}".format(rs.Fields("更新日").Value), end=",")
	print("{0:%Y/%m/%d}".format(rs.Fields("生年月日").Value))

	rs.Fields("管理者").Value = "0002"
	rs.Update()

	rs.MoveNext()

"""""""""""""""""""""""""""
接続解除
"""""""""""""""""""""""""""
if cn.State >= 1:
	cn.Close()

print("終了しました")

CursorTypes, LockTypes, and CursorLocations

※ MySQL は 以下の三つの組み合わせのみ動作
adUseClient/adOpenStatic
adUseServer/adOpenForwardOnly
adUseServer/adOpenDynamic

※ ADO でデフォルトは adUseServer

エディタのタブ設定



エディタの # コメント色

デフォルトが灰色で見にくいので濃い緑を使用しました





posted by lightbox at 2018-04-09 16:52 | Python | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します
container 終わり



フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

CSS ドロップシャドウの参考デモ
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり